mod reader;
mod writer;

pub use reader::{Reader, BasicReader};
pub use writer::{Writer, BasicWriter, CountWriter};

#[cfg(test)]
mod tests {
    use super::*;
    use std;
    use std::io::{Cursor, BufWriter};

    fn check(res: std::io::Result<()>) {
        match res {
            Ok(()) => {},
            Err(err) => {
                panic!(format!("unexpected error: {}", err))
            }
        }
    }

    #[test]
    fn count_u8_one_byte() {
        let mut cw = CountWriter::new();
        check(cw.write_u8(1));
        assert_eq!(cw.count(), 1)
    }

    #[test]
    fn count_u16_two_bytes() {
        let mut cw = CountWriter::new();
        check(cw.write_u16(3));
        assert_eq!(cw.count(), 2)
    }

    #[test]
    fn count_u32_four_bytes() {
        let mut cw = CountWriter::new();
        check(cw.write_u32(123));
        assert_eq!(cw.count(), 4)
    }

    #[test]
    fn count_u64_eight_bytes() {
        let mut cw = CountWriter::new();
        check(cw.write_u64(123));
        assert_eq!(cw.count(), 8)
    }

    #[test]
    fn count_bytes() {
        let mut cw = CountWriter::new();
        check(cw.write_bytes(&[1, 2, 3, 4]));
        assert_eq!(cw.count(), 4)
    }

    #[test]
    fn count_str() {
        let mut cw = CountWriter::new();
        check(cw.write_str("testing"));
        assert_eq!(cw.count(), 9)
    }

    #[test]
    fn count_string() {
        let mut cw = CountWriter::new();
        check(cw.write_string(&"testing".to_string()));
        assert_eq!(cw.count(), 9)
    }

    #[test]
    fn can_write_and_read() {
        let mut buf = [0 as u8; 64];
        {
            let mut write = BufWriter::new(&mut buf[..]);
            let mut writer = BasicWriter::new(&mut write);
            check(writer.write_u8(0xab));
            check(writer.write_u16(0xfedc));
            check(writer.write_u32(0xabcdef01));
            check(writer.write_u64(0xabcdef0102030405));
            check(writer.write_bytes(&[1, 2, 3, 4]));
            check(writer.write_string(&"Hello World".to_string()));
        }
        let mut cursor = Cursor::new(&mut buf[..]);
        let mut reader = BasicReader::new(&mut cursor);
        assert!(reader.read_u8().unwrap().unwrap() == 0xab);
        assert!(reader.read_u16().unwrap().unwrap() == 0xfedc);
        assert!(reader.read_u32().unwrap().unwrap() == 0xabcdef01);
        assert!(reader.read_u64().unwrap().unwrap() == 0xabcdef0102030405);

        let mut tmp = [0 as u8; 4];
        match reader.read_bytes(&mut tmp[..]) {
            Ok(4) => {
                assert!(tmp == [1, 2, 3, 4]);
            },
            Ok(n) => {
                assert!(false, format!("unexpected number of bytes read: {}", n));
            },
            Err(err) => {
                assert!(false, format!("read_bytes() failed unexpectedly: {}", err));
            }
        }

        match reader.read_string() {
            Ok(s) => {
                assert!(s.unwrap() == "Hello World".to_string());
            },
            Err(err) => panic!(format!("failed to read string: {}", err))
        }
    }
}

