pub mod de;
pub mod error;
pub mod hex;
pub mod ser;
pub mod set;
pub mod symbol;
pub mod value;

#[cfg(test)]
mod dom {
    use std::io;
    use super::value::*;

    #[derive(Debug, Hash, Clone, Ord, PartialEq, Eq, PartialOrd)]
    pub enum Dom {
        One,
        Two,
    }

    impl Domain for Dom {}

    impl std::str::FromStr for Dom {
        type Err = io::Error;
        fn from_str(s: &str) -> Result<Self, Self::Err> {
            match s {
                "One" => Ok(Dom::One),
                "Two" => Ok(Dom::Two),
                _ => Err(io::Error::new(io::ErrorKind::Other, "cannot parse preserves test domain")),
            }
        }
    }

    fn dom_as_preserves(v: &Dom) -> io::Result<UnwrappedIOValue> {
        Ok(match v {
            Dom::One => Value::bytestring(vec![255, 255, 255, 255]),
            Dom::Two => Value::symbol(&format!("Dom::{:?}", v)),
        })
    }

    #[test] fn test_one() {
        let v: PlainValue<_> = Value::from(vec![Value::from(1).wrap(),
                                                Value::Embedded(Dom::One).wrap(),
                                                Value::from(2).wrap()])
            .wrap();
        assert_eq!(PackedWriter::encode_iovalue(&v.copy_via(&mut dom_as_preserves).unwrap()).unwrap(),
                   [0xb5, 0x91, 0xb2, 0x04, 255, 255, 255, 255, 0x92, 0x84]);
    }

    #[test] fn test_two() {
        let v: PlainValue<_> = Value::from(vec![Value::from(1).wrap(),
                                                Value::Embedded(Dom::Two).wrap(),
                                                Value::from(2).wrap()])
            .wrap();
        assert_eq!(PackedWriter::encode_iovalue(&v.copy_via(&mut dom_as_preserves).unwrap()).unwrap(),
                   [0xb5, 0x91, 0xb3, 0x08, 68, 111, 109, 58, 58, 84, 119, 111, 0x92, 0x84]);
    }
}

#[cfg(test)]
mod ieee754_section_5_10_total_order_tests {
    use std::cmp::Ordering::{Less, Equal, Greater};
    use super::dom::Dom;

    use crate::value::{Value, PlainValue};
    fn f(val: f32) -> Value<PlainValue<Dom>> { Value::from(val) }
    fn d(val: f64) -> Value<PlainValue<Dom>> { Value::from(val) }

    // TODO: Test cases with a few different signalling and non-signalling NaNs

    #[test] fn case32_a_1() { assert_eq!(f(1.0).cmp(&f(2.0)), Less) }
    #[test] fn case32_a_2() { assert_eq!(f(-1.0).cmp(&f(1.0)), Less) }
    #[test] fn case32_a_3() { assert_eq!(f(0.0).cmp(&f(1.0)), Less) }
    #[test] fn case32_a_4() { assert_eq!(f(-1.0).cmp(&f(0.0)), Less) }
    #[test] fn case32_a_5() { assert_eq!(f(-1e32).cmp(&f(-1e31)), Less) }
    #[test] fn case32_a_6() { assert_eq!(f(-1e32).cmp(&f(1e33)), Less) }
    #[test] fn case32_a_7() {
        assert_eq!(f(std::f32::NEG_INFINITY).cmp(&f(std::f32::INFINITY)), Less)
    }
    #[test] fn case32_a_8() { assert_eq!(f(std::f32::NEG_INFINITY).cmp(&f(0.0)), Less) }
    #[test] fn case32_a_9() { assert_eq!(f(std::f32::NEG_INFINITY).cmp(&f(1.0)), Less) }
    #[test] fn case32_a_10() { assert_eq!(f(std::f32::NEG_INFINITY).cmp(&f(1e33)), Less) }
    #[test] fn case32_a_11() { assert_eq!(f(0.0).cmp(&f(std::f32::INFINITY)), Less) }
    #[test] fn case32_a_12() { assert_eq!(f(1.0).cmp(&f(std::f32::INFINITY)), Less) }
    #[test] fn case32_a_13() { assert_eq!(f(1e33).cmp(&f(std::f32::INFINITY)), Less) }

    #[test] fn case32_b_1() { assert_eq!(f(2.0).cmp(&f(1.0)), Greater) }
    #[test] fn case32_b_2() { assert_eq!(f(1.0).cmp(&f(-1.0)), Greater) }
    #[test] fn case32_b_3() { assert_eq!(f(1.0).cmp(&f(0.0)), Greater) }
    #[test] fn case32_b_4() { assert_eq!(f(0.0).cmp(&f(-1.0)), Greater) }
    #[test] fn case32_b_5() { assert_eq!(f(-1e31).cmp(&f(-1e32)), Greater) }
    #[test] fn case32_b_6() { assert_eq!(f(1e33).cmp(&f(-1e32)), Greater) }
    #[test] fn case32_b_7() {
        assert_eq!(f(std::f32::INFINITY).cmp(&f(std::f32::NEG_INFINITY)), Greater)
    }
    #[test] fn case32_b_8() { assert_eq!(f(std::f32::INFINITY).cmp(&f(0.0)), Greater) }
    #[test] fn case32_b_9() { assert_eq!(f(std::f32::INFINITY).cmp(&f(1.0)), Greater) }
    #[test] fn case32_b_10() { assert_eq!(f(std::f32::INFINITY).cmp(&f(1e33)), Greater) }
    #[test] fn case32_b_11() { assert_eq!(f(0.0).cmp(&f(std::f32::NEG_INFINITY)), Greater) }
    #[test] fn case32_b_12() { assert_eq!(f(1.0).cmp(&f(std::f32::NEG_INFINITY)), Greater) }
    #[test] fn case32_b_13() { assert_eq!(f(1e33).cmp(&f(std::f32::NEG_INFINITY)), Greater) }

    #[test] fn case32_c1() { assert_eq!(f(-0.0).cmp(&f( 0.0)), Less) }
    #[test] fn case32_c2() { assert_eq!(f( 0.0).cmp(&f(-0.0)), Greater) }
    #[test] fn case32_c3_1() { assert_eq!(f(-0.0).cmp(&f(-0.0)), Equal) }
    #[test] fn case32_c3_2() { assert_eq!(f( 0.0).cmp(&f( 0.0)), Equal) }
    #[test] fn case32_c3_3() { assert_eq!(f(1.0).cmp(&f(1.0)), Equal) }
    #[test] fn case32_c3_4() { assert_eq!(f(-1.0).cmp(&f(-1.0)), Equal) }
    #[test] fn case32_c3_5() { assert_eq!(f(-1e32).cmp(&f(-1e32)), Equal) }
    #[test] fn case32_c3_6() { assert_eq!(f(1e33).cmp(&f(1e33)), Equal) }


    #[test] fn case64_a_1() { assert_eq!(d(1.0).cmp(&d(2.0)), Less) }
    #[test] fn case64_a_2() { assert_eq!(d(-1.0).cmp(&d(1.0)), Less) }
    #[test] fn case64_a_3() { assert_eq!(d(0.0).cmp(&d(1.0)), Less) }
    #[test] fn case64_a_4() { assert_eq!(d(-1.0).cmp(&d(0.0)), Less) }
    #[test] fn case64_a_5() { assert_eq!(d(-1e32).cmp(&d(-1e31)), Less) }
    #[test] fn case64_a_6() { assert_eq!(d(-1e32).cmp(&d(1e33)), Less) }
    #[test] fn case64_a_7() {
        assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(std::f64::INFINITY)), Less)
    }
    #[test] fn case64_a_8() { assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(0.0)), Less) }
    #[test] fn case64_a_9() { assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(1.0)), Less) }
    #[test] fn case64_a_10() { assert_eq!(d(std::f64::NEG_INFINITY).cmp(&d(1e33)), Less) }
    #[test] fn case64_a_11() { assert_eq!(d(0.0).cmp(&d(std::f64::INFINITY)), Less) }
    #[test] fn case64_a_12() { assert_eq!(d(1.0).cmp(&d(std::f64::INFINITY)), Less) }
    #[test] fn case64_a_13() { assert_eq!(d(1e33).cmp(&d(std::f64::INFINITY)), Less) }

    #[test] fn case64_b_1() { assert_eq!(d(2.0).cmp(&d(1.0)), Greater) }
    #[test] fn case64_b_2() { assert_eq!(d(1.0).cmp(&d(-1.0)), Greater) }
    #[test] fn case64_b_3() { assert_eq!(d(1.0).cmp(&d(0.0)), Greater) }
    #[test] fn case64_b_4() { assert_eq!(d(0.0).cmp(&d(-1.0)), Greater) }
    #[test] fn case64_b_5() { assert_eq!(d(-1e31).cmp(&d(-1e32)), Greater) }
    #[test] fn case64_b_6() { assert_eq!(d(1e33).cmp(&d(-1e32)), Greater) }
    #[test] fn case64_b_7() {
        assert_eq!(d(std::f64::INFINITY).cmp(&d(std::f64::NEG_INFINITY)), Greater)
    }
    #[test] fn case64_b_8() { assert_eq!(d(std::f64::INFINITY).cmp(&d(0.0)), Greater) }
    #[test] fn case64_b_9() { assert_eq!(d(std::f64::INFINITY).cmp(&d(1.0)), Greater) }
    #[test] fn case64_b_10() { assert_eq!(d(std::f64::INFINITY).cmp(&d(1e33)), Greater) }
    #[test] fn case64_b_11() { assert_eq!(d(0.0).cmp(&d(std::f64::NEG_INFINITY)), Greater) }
    #[test] fn case64_b_12() { assert_eq!(d(1.0).cmp(&d(std::f64::NEG_INFINITY)), Greater) }
    #[test] fn case64_b_13() { assert_eq!(d(1e33).cmp(&d(std::f64::NEG_INFINITY)), Greater) }

    #[test] fn case64_c1() { assert_eq!(d(-0.0).cmp(&d( 0.0)), Less) }
    #[test] fn case64_c2() { assert_eq!(d( 0.0).cmp(&d(-0.0)), Greater) }
    #[test] fn case64_c3_1() { assert_eq!(d(-0.0).cmp(&d(-0.0)), Equal) }
    #[test] fn case64_c3_2() { assert_eq!(d( 0.0).cmp(&d( 0.0)), Equal) }
    #[test] fn case64_c3_3() { assert_eq!(d(1.0).cmp(&d(1.0)), Equal) }
    #[test] fn case64_c3_4() { assert_eq!(d(-1.0).cmp(&d(-1.0)), Equal) }
    #[test] fn case64_c3_5() { assert_eq!(d(-1e32).cmp(&d(-1e32)), Equal) }
    #[test] fn case64_c3_6() { assert_eq!(d(1e33).cmp(&d(1e33)), Equal) }
}

#[cfg(test)]
mod value_tests {
    use crate::value::{Value, PlainValue, repr::Record, signed_integer::SignedInteger};
    use super::dom::Dom;

    type VV = Value<PlainValue<Dom>>;

    #[test] fn boolean_mut() {
        let mut b = VV::Boolean(true);
        assert!(b.is_boolean());
        *(b.as_boolean_mut().unwrap()) = false;
        assert_eq!(b, VV::Boolean(false));
    }

    #[test] fn float_mut() {
        let mut f = VV::from(1.0f32);
        assert!(f.is_f32());
        *(f.as_f32_mut().unwrap()) = 123.45;
        assert_eq!(f, VV::from(123.45f32));
        assert_eq!((f.as_f32().unwrap() - 123.45f32).abs() < std::f32::EPSILON, true);
    }

    #[test] fn double_mut() {
        let mut f = VV::from(1.0);
        assert!(f.is_f64());
        *(f.as_f64_mut().unwrap()) = 123.45;
        assert_eq!(f, VV::from(123.45));
        assert_eq!((f.as_f64().unwrap() - 123.45).abs() < std::f64::EPSILON, true);
    }

    #[test] fn signedinteger_mut() {
        let mut i = VV::from(123);
        assert!(i.is_signedinteger());
        *(i.as_signedinteger_mut().unwrap()) = SignedInteger::from(234i128);
        assert_eq!(i, VV::from(234));
        assert_eq!(i.as_i().unwrap(), 234);
    }

    #[test] fn string_mut() {
        let mut s = VV::from("hello, world!");
        assert!(s.is_string());
        s.as_string_mut().unwrap().replace_range(7..12, "there");
        assert_eq!(s, VV::from("hello, there!"));
    }

    #[test] fn bytes_mut() {
        let mut b = VV::from(&b"hello, world!"[..]);
        assert!(b.is_bytestring());
        b.as_bytestring_mut().unwrap().splice(7..12, Vec::from(&b"there"[..]));
        assert_eq!(b, VV::from(&b"hello, there!"[..]));
    }

    #[test] fn symbol_mut() {
        let mut s = VV::symbol("abcd");
        assert!(s.is_symbol());
        s.as_symbol_mut().unwrap().replace_range(..2, "AB");
        assert_eq!(s, VV::symbol("ABcd"));
    }

    #[test] fn record_mut() {
        let says = VV::symbol("says").wrap();
        let mut r = VV::Record(Record(vec![says.clone(), VV::from("Tony").wrap(), VV::from("Hello!").wrap()]));
        assert_eq!(r.as_record_mut(Some(0)), None);
        assert_eq!(r.as_record_mut(Some(1)), None);
        assert!(r.as_record_mut(Some(2)).is_some());
        assert_eq!(r.as_record_mut(Some(3)), None);
        r.as_record_mut(None).unwrap().fields_mut()[0] = VV::from("Alice").wrap();
        assert_eq!(r, VV::Record(Record(vec![says, VV::from("Alice").wrap(), VV::from("Hello!").wrap()])));
    }

    #[test] fn sequence_mut() {
        let mut s = VV::Sequence(vec![VV::from(1).wrap(),
                                      VV::from(2).wrap(),
                                      VV::from(3).wrap()]);
        let r = VV::Sequence(vec![VV::from(1).wrap(),
                                  VV::from(99).wrap(),
                                  VV::from(3).wrap()]);
        s.as_sequence_mut().unwrap()[1] = VV::from(99).wrap();
        assert_eq!(r, s);
    }
}

#[cfg(test)]
mod decoder_tests {
    use crate::value::{Value, NestedValue, BinarySource, BytesBinarySource, ConfiguredReader};
    use crate::de::from_bytes;
    use crate::error::{Error, ExpectedKind, is_eof_io_error};

    fn expect_number_out_of_range<T: core::fmt::Debug>(r: Result<T, Error>) {
        match r {
            Ok(v) => panic!("Expected NumberOutOfRange, but got a parse of {:?}", v),
            Err(Error::NumberOutOfRange(_)) => (),
            Err(e) => panic!("Expected NumberOutOfRange, but got an error of {:?}", e),
        }
    }

    fn expect_expected<T: core::fmt::Debug>(k: ExpectedKind, r: Result<T, Error>) {
        match r {
            Ok(v) => panic!("Expected Expected({:?}), but got a parse of {:?}", k, v),
            Err(Error::Expected(k1, _)) if k1 == k => (),
            Err(e) => panic!("Expected Expected({:?}), but got an error of {:?}", k, e),
        }
    }

    #[test] fn skip_annotations_noskip() {
        let buf = &b"\x85\x92\x91"[..];
        let mut src = BytesBinarySource::new(&buf);
        let mut d = ConfiguredReader::new(src.packed_iovalues());
        let v = d.demand_next().unwrap();
        assert_eq!(v.annotations().slice().len(), 1);
        assert_eq!(v.annotations().slice()[0], Value::from(2).wrap());
        assert_eq!(v.value(), &Value::from(1));
    }

    #[test] fn skip_annotations_skip() {
        let buf = &b"\x85\x92\x91"[..];
        let mut src = BytesBinarySource::new(&buf);
        let mut d = ConfiguredReader::new(src.packed_iovalues());
        d.set_read_annotations(false);
        let v = d.demand_next().unwrap();
        assert_eq!(v.annotations().slice().len(), 0);
        assert_eq!(v.value(), &Value::from(1));
    }

    #[test] fn multiple_values_buf_advanced() {
        let buf = &b"\xb4\xb3\x04Ping\x84\xb4\xb3\x04Pong\x84"[..];
        assert_eq!(buf.len(), 16);
        let mut src = BytesBinarySource::new(&buf);
        let mut d = ConfiguredReader::new(src.packed_iovalues());
        assert_eq!(d.reader.source.index, 0);
        assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record0("Ping"));
        assert_eq!(d.reader.source.index, 8);
        assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record0("Pong"));
        assert_eq!(d.reader.source.index, 16);
        assert!(d.next().is_none());
        assert!(if let Err(e) = d.demand_next() { is_eof_io_error(&e) } else { false });
    }

    #[test] fn direct_i8_format_a_positive()      { assert_eq!(from_bytes::<i8>(b"\x91").unwrap(), 1) }
    #[test] fn direct_i8_format_a_zero()          { assert_eq!(from_bytes::<i8>(b"\x90").unwrap(), 0) }
    #[test] fn direct_i8_format_a_negative()      { assert_eq!(from_bytes::<i8>(b"\x9f").unwrap(), -1) }
    #[test] fn direct_i8_format_b()               { assert_eq!(from_bytes::<i8>(b"\xa0\xfe").unwrap(), -2) }
    #[test] fn direct_i8_format_b_too_long()      { assert_eq!(from_bytes::<i8>(b"\xa2\xff\xff\xfe").unwrap(), -2) }
    #[test] fn direct_i8_format_b_much_too_long() { assert_eq!(from_bytes::<i8>(b"\xa9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe").unwrap(), -2) }

    #[test] fn direct_u8_format_a_positive()      { assert_eq!(from_bytes::<u8>(b"\x91").unwrap(), 1) }
    #[test] fn direct_u8_format_a_zero()          { assert_eq!(from_bytes::<u8>(b"\x90").unwrap(), 0) }
    #[test] fn direct_u8_format_b()               { assert_eq!(from_bytes::<u8>(b"\xa01").unwrap(), 49) }
    #[test] fn direct_u8_format_b_too_long()      { assert_eq!(from_bytes::<u8>(b"\xa3\0\0\01").unwrap(), 49) }
    #[test] fn direct_u8_format_b_much_too_long() { assert_eq!(from_bytes::<u8>(b"\xa9\0\0\0\0\0\0\0\0\01").unwrap(), 49) }

    #[test] fn direct_i16_format_a()              { assert_eq!(from_bytes::<i16>(b"\x9e").unwrap(), -2) }
    #[test] fn direct_i16_format_b()              { assert_eq!(from_bytes::<i16>(b"\xa1\xfe\xff").unwrap(), -257) }

    #[test] fn direct_u8_wrong_format() {
        expect_expected(ExpectedKind::SignedInteger, from_bytes::<u8>(b"\xb1\x05bogus"))
    }

    #[test] fn direct_u8_format_b_too_large() {
        expect_number_out_of_range(from_bytes::<u8>(b"\xa3\0\011"))
    }

    #[test] fn direct_i8_format_b_too_large() {
        expect_number_out_of_range(from_bytes::<i8>(b"\xa1\xfe\xff"))
    }

    #[test] fn direct_i16_format_b_too_large() {
        expect_number_out_of_range(from_bytes::<i16>(b"\xa2\xfe\xff\xff"));
    }

    #[test] fn direct_i32_format_b_ok() {
        assert_eq!(from_bytes::<i32>(b"\xa2\xfe\xff\xff").unwrap(), -65537);
    }

    #[test] fn direct_i32_format_b_ok_2() {
        assert_eq!(from_bytes::<i32>(b"\xa3\xfe\xff\xff\xff").unwrap(), -16777217);
    }

    #[test] fn direct_i64_format_b() {
        assert_eq!(from_bytes::<i64>(b"\xa0\xff").unwrap(), -1);
        assert_eq!(from_bytes::<i64>(b"\xa2\xff\xff\xff").unwrap(), -1);
        assert_eq!(from_bytes::<i64>(b"\xa9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff").unwrap(), -1);
        assert_eq!(from_bytes::<i64>(b"\xa0\xfe").unwrap(), -2);
        assert_eq!(from_bytes::<i64>(b"\xa2\xff\xfe\xff").unwrap(), -257);
        assert_eq!(from_bytes::<i64>(b"\xa2\xfe\xff\xff").unwrap(), -65537);
        assert_eq!(from_bytes::<i64>(b"\xa9\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff").unwrap(), -16777217);
        assert_eq!(from_bytes::<i64>(b"\xa9\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff").unwrap(), -72057594037927937);
        expect_number_out_of_range(from_bytes::<i64>(b"\xa9\xff\xff\x0e\xff\xff\xff\xff\xff\xff\xff"));
        expect_number_out_of_range(from_bytes::<i64>(b"\xa8\xff\x0e\xff\xff\xff\xff\xff\xff\xff"));
        expect_number_out_of_range(from_bytes::<i64>(b"\xa8\x80\x0e\xff\xff\xff\xff\xff\xff\xff"));
        expect_number_out_of_range(from_bytes::<i64>(b"\xa9\xff\x00\x0e\xff\xff\xff\xff\xff\xff\xff"));
        assert_eq!(from_bytes::<i64>(b"\xa7\xfe\xff\xff\xff\xff\xff\xff\xff").unwrap(), -72057594037927937);
        assert_eq!(from_bytes::<i64>(b"\xa7\x0e\xff\xff\xff\xff\xff\xff\xff").unwrap(), 1080863910568919039);
        assert_eq!(from_bytes::<i64>(b"\xa7\x80\0\0\0\0\0\0\0").unwrap(), -9223372036854775808);
        assert_eq!(from_bytes::<i64>(b"\xa7\0\0\0\0\0\0\0\0").unwrap(), 0);
        assert_eq!(from_bytes::<i64>(b"\x90").unwrap(), 0);
        assert_eq!(from_bytes::<i64>(b"\xa7\x7f\xff\xff\xff\xff\xff\xff\xff").unwrap(), 9223372036854775807);
    }

    #[test] fn direct_u64_format_b() {
        expect_number_out_of_range(from_bytes::<u64>(b"\xa0\xff"));
        assert_eq!(from_bytes::<u64>(b"\xa1\0\xff").unwrap(), 255);
        expect_number_out_of_range(from_bytes::<u64>(b"\xa2\xff\xff\xff"));
        assert_eq!(from_bytes::<u64>(b"\xa3\0\xff\xff\xff").unwrap(), 0xffffff);
        expect_number_out_of_range(from_bytes::<u64>(b"\xa9\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff"));
        assert_eq!(from_bytes::<u64>(b"\xa0\x02").unwrap(), 2);
        assert_eq!(from_bytes::<u64>(b"\xa2\x00\x01\x00").unwrap(), 256);
        assert_eq!(from_bytes::<u64>(b"\xa2\x01\x00\x00").unwrap(), 65536);
        assert_eq!(from_bytes::<u64>(b"\xa9\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00").unwrap(), 16777216);
        assert_eq!(from_bytes::<u64>(b"\xa9\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00").unwrap(), 72057594037927936);
        assert_eq!(from_bytes::<u64>(b"\xa9\x00\x00\xf2\x00\x00\x00\x00\x00\x00\x00").unwrap(), 0xf200000000000000);
        assert_eq!(from_bytes::<u64>(b"\xa9\x00\x00\x72\x00\x00\x00\x00\x00\x00\x00").unwrap(), 0x7200000000000000);
        expect_number_out_of_range(from_bytes::<u64>(b"\xa9\x00\xf2\x00\x00\x00\x00\x00\x00\x00\x00"));
        assert_eq!(from_bytes::<u64>(b"\xa8\x00\xf2\x00\x00\x00\x00\x00\x00\x00").unwrap(), 0xf200000000000000);
        expect_number_out_of_range(from_bytes::<u64>(b"\xa8\x7f\xf2\x00\x00\x00\x00\x00\x00\x00"));
        expect_number_out_of_range(from_bytes::<u64>(b"\xa9\x00\xff\xf2\x00\x00\x00\x00\x00\x00\x00"));
        assert_eq!(from_bytes::<u64>(b"\xa7\x01\x00\x00\x00\x00\x00\x00\x00").unwrap(), 72057594037927936);
        assert_eq!(from_bytes::<u64>(b"\xa7\x0e\xff\xff\xff\xff\xff\xff\xff").unwrap(), 1080863910568919039);
        expect_number_out_of_range(from_bytes::<u64>(b"\xa7\x80\0\0\0\0\0\0\0"));
        assert_eq!(from_bytes::<u64>(b"\xa8\0\x80\0\0\0\0\0\0\0").unwrap(), 9223372036854775808);
        assert_eq!(from_bytes::<u64>(b"\xa7\0\0\0\0\0\0\0\0").unwrap(), 0);
        assert_eq!(from_bytes::<u64>(b"\x90").unwrap(), 0);
        assert_eq!(from_bytes::<u64>(b"\xa7\x7f\xff\xff\xff\xff\xff\xff\xff").unwrap(), 9223372036854775807);
    }
}

#[cfg(test)]
mod formatting_tests {
    use super::dom::Dom;
    use super::value::ArcValue;
    use super::value::IOValue;
    use super::value::Value;

    #[test] fn format_debug_and_parse() {
        let v = "[1, {z: 2, a: #!\"One\"}, 3]".parse::<Value<ArcValue<Dom>>>().unwrap();
        assert_eq!(format!("{:?}", &v), "[1, {a: #!\"One\", z: 2}, 3]");
    }

    #[test] fn format_pretty_debug_and_parse() {
        let v = "[1, {z: 2, a: #!\"One\"}, 3]".parse::<Value<ArcValue<Dom>>>().unwrap();
        assert_eq!(format!("{:#?}", &v), concat!(
            "[\n",
            "    1,\n",
            "    {\n",
            "        a: #!\"One\",\n",
            "        z: 2\n",
            "    },\n",
            "    3\n",
            "]"));
    }

    #[test] fn iovalue_parse() {
        let v = "[1 @{a:b c:d} @\"foo\" #![2 3] 4]".parse::<IOValue>().unwrap();
        assert_eq!(format!("{:#?}", &v), concat!(
            "[\n",
            "    1,\n",
            "    @{\n",
            "        a: b,\n",
            "        c: d\n",
            "    } @\"foo\" #![\n",
            "        2,\n",
            "        3\n",
            "    ],\n",
            "    4\n",
            "]"));
    }
}

#[cfg(test)]
mod serde_tests {
    use crate::symbol::Symbol;
    use crate::de::from_bytes as deserialize_from_bytes;
    use crate::value::de::from_value as deserialize_from_value;
    use crate::value::to_value;
    use crate::value::{Value, IOValue, Map, Set};
    use crate::value::packed::PackedWriter;

    #[test] fn simple_to_value() {
        use serde::Serialize;
        #[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
        struct Colour{ red: u8, green: u8, blue: u8 }
        #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
        struct SimpleValue<'a>(String,
                               #[serde(with = "crate::symbol")] String,
                               Symbol,
                               #[serde(with = "crate::symbol")] String,
                               Symbol,
                               &'a str,
                               #[serde(with = "serde_bytes")] &'a [u8],
                               #[serde(with = "serde_bytes")] Vec<u8>,
                               Vec<bool>,
                               #[serde(with = "crate::set")] Set<String>,
                               i16,
                               IOValue,
                               Map<String, Colour>,
                               f32,
                               f64);
        let mut str_set = Set::new();
        str_set.insert("one".to_owned());
        str_set.insert("two".to_owned());
        str_set.insert("three".to_owned());
        let mut colours = Map::new();
        colours.insert("red".to_owned(), Colour { red: 255, green: 0, blue: 0 });
        colours.insert("green".to_owned(), Colour { red: 0, green: 255, blue: 0 });
        colours.insert("blue".to_owned(), Colour { red: 0, green: 0, blue: 255 });
        let v = SimpleValue("hello".to_string(),
                            "sym1".to_string(),
                            Symbol("sym2".to_string()),
                            "sym3".to_string(),
                            Symbol("sym4".to_string()),
                            "world",
                            &b"slice"[..],
                            b"vec".to_vec(),
                            vec![false, true, false, true],
                            str_set,
                            12345,
                            Value::from("hi").wrap(),
                            colours,
                            12.345,
                            12.3456789);
        println!("== v: {:#?}", v);
        let w: IOValue = to_value(&v);
        println!("== w: {:#?}", w);
        let x = deserialize_from_value(&w).unwrap();
        println!("== x: {:#?}", &x);
        assert_eq!(v, x);

        let expected_bytes = vec![
            0xb4, // Struct
              0xb3, 0x0b, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, // SimpleValue
              0xb1, 0x05, 0x68, 0x65, 0x6c, 0x6c, 0x6f, // "hello"
              0xb3, 0x04, 0x73, 0x79, 0x6d, 0x31, // sym1
              0xb3, 0x04, 0x73, 0x79, 0x6d, 0x32, // sym2
              0xb3, 0x04, 0x73, 0x79, 0x6d, 0x33, // sym3
              0xb3, 0x04, 0x73, 0x79, 0x6d, 0x34, // sym4
              0xb1, 0x05, 0x77, 0x6f, 0x72, 0x6c, 0x64, // "world"
              0xb2, 0x05, 0x73, 0x6c, 0x69, 0x63, 0x65, // #"slice"
              0xb2, 0x03, 0x76, 0x65, 0x63, // #"vec"
              0xb5, // Sequence
                0x80, // false
                0x81, // true
                0x80, // false
                0x81, // true
              0x84,
              0xb6, // Set
                0xb1, 0x03, 0x6f, 0x6e, 0x65,
                0xb1, 0x03, 0x74, 0x77, 0x6f,
                0xb1, 0x05, 0x74, 0x68, 0x72, 0x65, 0x65,
              0x84,
              0xa1, 0x30, 0x39, // 12345
              0xb1, 0x02, 0x68, 0x69, // "hi"
              0xb7, // Dictionary
                0xb1, 0x03, 0x72, 0x65, 0x64, // "red"
                  0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72,  0xa1, 0x00, 0xff, 0x90, 0x90,  0x84,
                0xb1, 0x04, 0x62, 0x6c, 0x75, 0x65, // "blue"
                  0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72,  0x90, 0x90, 0xa1, 0x00, 0xff,  0x84,
                0xb1, 0x05, 0x67, 0x72, 0x65, 0x65, 0x6e, // "green"
                  0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72,  0x90, 0xa1, 0x00, 0xff, 0x90,  0x84,
              0x84,

              0x82, 0x41, 0x45, 0x85, 0x1f, // 12.345,
              0x83, 0x40, 0x28, 0xb0, 0xfc, 0xd3, 0x24, 0xd5, 0xa2, // 12.3456789
            0x84,
        ];

        let y = deserialize_from_bytes(&expected_bytes).unwrap();
        println!("== y: {:#?}", &y);
        assert_eq!(v, y);

        let v_bytes_1 = PackedWriter::encode_iovalue(&w).unwrap();
        println!("== w bytes = {:?}", v_bytes_1);
        assert_eq!(expected_bytes, v_bytes_1);

        let mut v_bytes_2 = Vec::new();
        v.serialize(&mut crate::ser::Serializer::new(&mut PackedWriter::new(&mut v_bytes_2))).unwrap();
        println!("== v bytes = {:?}", v_bytes_2);
        assert_eq!(v_bytes_1, v_bytes_2);
    }
}
