967 lines
28 KiB
Rust
967 lines
28 KiB
Rust
#![doc = concat!(
|
|
include_str!("../README.md"),
|
|
"# What is Preserves?\n\n",
|
|
include_str!("../doc/what-is-preserves.md"),
|
|
)]
|
|
|
|
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 super::value::*;
|
|
use std::io;
|
|
|
|
#[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, 0xb0, 0x01, 0x01, 0xb2, 0x04, 255, 255, 255, 255, 0xb0, 0x01, 0x02, 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, 0xb0, 0x01, 0x01, 0xb3, 0x08, 68, 111, 109, 58, 58, 84, 119, 111, 0xb0, 0x01, 0x02, 0x84]
|
|
);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod ieee754_section_5_10_total_order_tests {
|
|
use super::dom::Dom;
|
|
use std::cmp::Ordering::{Equal, Greater, Less};
|
|
|
|
use crate::value::{PlainValue, Value};
|
|
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 super::dom::Dom;
|
|
use crate::value::{repr::Record, signed_integer::SignedInteger, PlainValue, Value};
|
|
|
|
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::de::from_bytes;
|
|
use crate::error::{is_eof_io_error, Error, ExpectedKind};
|
|
use crate::value::{BinarySource, BytesBinarySource, ConfiguredReader, NestedValue, Value};
|
|
|
|
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\xB0\x01\x02\xB0\x01\x01"[..];
|
|
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\xB0\x01\x02\xB0\x01\x01"[..];
|
|
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"\xB0\x01\x01").unwrap(), 1)
|
|
}
|
|
#[test]
|
|
fn direct_i8_format_a_zero() {
|
|
assert_eq!(from_bytes::<i8>(b"\xB0\x00").unwrap(), 0)
|
|
}
|
|
#[test]
|
|
fn direct_i8_format_a_negative() {
|
|
assert_eq!(from_bytes::<i8>(b"\xB0\x01\xff").unwrap(), -1)
|
|
}
|
|
#[test]
|
|
fn direct_i8_format_b() {
|
|
assert_eq!(from_bytes::<i8>(b"\xb0\x01\xfe").unwrap(), -2)
|
|
}
|
|
#[test]
|
|
fn direct_i8_format_b_too_long() {
|
|
assert_eq!(from_bytes::<i8>(b"\xb0\x03\xff\xff\xfe").unwrap(), -2)
|
|
}
|
|
#[test]
|
|
fn direct_i8_format_b_much_too_long() {
|
|
assert_eq!(
|
|
from_bytes::<i8>(b"\xb0\x0a\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"\xB0\x01\x01").unwrap(), 1)
|
|
}
|
|
#[test]
|
|
fn direct_u8_format_a_zero() {
|
|
assert_eq!(from_bytes::<u8>(b"\xB0\x00").unwrap(), 0)
|
|
}
|
|
#[test]
|
|
fn direct_u8_format_b() {
|
|
assert_eq!(from_bytes::<u8>(b"\xb0\x011").unwrap(), 49)
|
|
}
|
|
#[test]
|
|
fn direct_u8_format_b_too_long() {
|
|
assert_eq!(from_bytes::<u8>(b"\xb0\x04\0\0\01").unwrap(), 49)
|
|
}
|
|
#[test]
|
|
fn direct_u8_format_b_much_too_long() {
|
|
assert_eq!(from_bytes::<u8>(b"\xb0\x0a\0\0\0\0\0\0\0\0\01").unwrap(), 49)
|
|
}
|
|
|
|
#[test]
|
|
fn direct_i16_format_a() {
|
|
assert_eq!(from_bytes::<i16>(b"\xB0\x01\xfe").unwrap(), -2)
|
|
}
|
|
#[test]
|
|
fn direct_i16_format_b() {
|
|
assert_eq!(from_bytes::<i16>(b"\xb0\x02\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"\xb0\x04\0\011"))
|
|
}
|
|
|
|
#[test]
|
|
fn direct_i8_format_b_too_large() {
|
|
expect_number_out_of_range(from_bytes::<i8>(b"\xb0\x02\xfe\xff"))
|
|
}
|
|
|
|
#[test]
|
|
fn direct_i16_format_b_too_large() {
|
|
expect_number_out_of_range(from_bytes::<i16>(b"\xb0\x03\xfe\xff\xff"));
|
|
}
|
|
|
|
#[test]
|
|
fn direct_i32_format_b_ok() {
|
|
assert_eq!(from_bytes::<i32>(b"\xb0\x03\xfe\xff\xff").unwrap(), -65537);
|
|
}
|
|
|
|
#[test]
|
|
fn direct_i32_format_b_ok_2() {
|
|
assert_eq!(
|
|
from_bytes::<i32>(b"\xb0\x04\xfe\xff\xff\xff").unwrap(),
|
|
-16777217
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn direct_i64_format_b() {
|
|
assert_eq!(from_bytes::<i64>(b"\xb0\x01\xff").unwrap(), -1);
|
|
assert_eq!(from_bytes::<i64>(b"\xb0\x03\xff\xff\xff").unwrap(), -1);
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff").unwrap(),
|
|
-1
|
|
);
|
|
assert_eq!(from_bytes::<i64>(b"\xb0\x01\xfe").unwrap(), -2);
|
|
assert_eq!(from_bytes::<i64>(b"\xb0\x03\xff\xfe\xff").unwrap(), -257);
|
|
assert_eq!(from_bytes::<i64>(b"\xb0\x03\xfe\xff\xff").unwrap(), -65537);
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff").unwrap(),
|
|
-16777217
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x0a\xff\xff\xfe\xff\xff\xff\xff\xff\xff\xff").unwrap(),
|
|
-72057594037927937
|
|
);
|
|
expect_number_out_of_range(from_bytes::<i64>(
|
|
b"\xb0\x0a\xff\xff\x0e\xff\xff\xff\xff\xff\xff\xff",
|
|
));
|
|
expect_number_out_of_range(from_bytes::<i64>(
|
|
b"\xb0\x09\xff\x0e\xff\xff\xff\xff\xff\xff\xff",
|
|
));
|
|
expect_number_out_of_range(from_bytes::<i64>(
|
|
b"\xb0\x09\x80\x0e\xff\xff\xff\xff\xff\xff\xff",
|
|
));
|
|
expect_number_out_of_range(from_bytes::<i64>(
|
|
b"\xb0\x0a\xff\x00\x0e\xff\xff\xff\xff\xff\xff\xff",
|
|
));
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x08\xfe\xff\xff\xff\xff\xff\xff\xff").unwrap(),
|
|
-72057594037927937
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x08\x0e\xff\xff\xff\xff\xff\xff\xff").unwrap(),
|
|
1080863910568919039
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x08\x80\0\0\0\0\0\0\0").unwrap(),
|
|
-9223372036854775808
|
|
);
|
|
assert_eq!(from_bytes::<i64>(b"\xb0\x08\0\0\0\0\0\0\0\0").unwrap(), 0);
|
|
assert_eq!(from_bytes::<i64>(b"\xB0\x00").unwrap(), 0);
|
|
assert_eq!(
|
|
from_bytes::<i64>(b"\xb0\x08\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"\xb0\x01\xff"));
|
|
assert_eq!(from_bytes::<u64>(b"\xb0\x02\0\xff").unwrap(), 255);
|
|
expect_number_out_of_range(from_bytes::<u64>(b"\xb0\x03\xff\xff\xff"));
|
|
assert_eq!(from_bytes::<u64>(b"\xb0\x04\0\xff\xff\xff").unwrap(), 0xffffff);
|
|
expect_number_out_of_range(from_bytes::<u64>(
|
|
b"\xb0\x0a\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff",
|
|
));
|
|
assert_eq!(from_bytes::<u64>(b"\xb0\x01\x02").unwrap(), 2);
|
|
assert_eq!(from_bytes::<u64>(b"\xb0\x03\x00\x01\x00").unwrap(), 256);
|
|
assert_eq!(from_bytes::<u64>(b"\xb0\x03\x01\x00\x00").unwrap(), 65536);
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x0a\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00").unwrap(),
|
|
16777216
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x0a\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00").unwrap(),
|
|
72057594037927936
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x0a\x00\x00\xf2\x00\x00\x00\x00\x00\x00\x00").unwrap(),
|
|
0xf200000000000000
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x0a\x00\x00\x72\x00\x00\x00\x00\x00\x00\x00").unwrap(),
|
|
0x7200000000000000
|
|
);
|
|
expect_number_out_of_range(from_bytes::<u64>(
|
|
b"\xb0\x0a\x00\xf2\x00\x00\x00\x00\x00\x00\x00\x00",
|
|
));
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x09\x00\xf2\x00\x00\x00\x00\x00\x00\x00").unwrap(),
|
|
0xf200000000000000
|
|
);
|
|
expect_number_out_of_range(from_bytes::<u64>(
|
|
b"\xb0\x09\x7f\xf2\x00\x00\x00\x00\x00\x00\x00",
|
|
));
|
|
expect_number_out_of_range(from_bytes::<u64>(
|
|
b"\xb0\x0a\x00\xff\xf2\x00\x00\x00\x00\x00\x00\x00",
|
|
));
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x08\x01\x00\x00\x00\x00\x00\x00\x00").unwrap(),
|
|
72057594037927936
|
|
);
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x08\x0e\xff\xff\xff\xff\xff\xff\xff").unwrap(),
|
|
1080863910568919039
|
|
);
|
|
expect_number_out_of_range(from_bytes::<u64>(b"\xb0\x08\x80\0\0\0\0\0\0\0"));
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x09\0\x80\0\0\0\0\0\0\0").unwrap(),
|
|
9223372036854775808
|
|
);
|
|
assert_eq!(from_bytes::<u64>(b"\xb0\x08\0\0\0\0\0\0\0\0").unwrap(), 0);
|
|
assert_eq!(from_bytes::<u64>(b"\xB0\x00").unwrap(), 0);
|
|
assert_eq!(
|
|
from_bytes::<u64>(b"\xb0\x08\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::de::from_bytes as deserialize_from_bytes;
|
|
use crate::symbol::Symbol;
|
|
use crate::value::de::from_value as deserialize_from_value;
|
|
use crate::value::packed::PackedWriter;
|
|
use crate::value::to_value;
|
|
use crate::value::{IOValue, Map, Set, Value};
|
|
|
|
#[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, 0xb0, 0x02, 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, 0xb0, 0x02, 0x00, 0xff, 0xb0, 0x00, 0xb0, 0x00,
|
|
0x84, 0xb1, 0x04, 0x62, 0x6c, 0x75, 0x65, // "blue"
|
|
0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0xb0, 0x00, 0xb0, 0x00, 0xb0, 0x02, 0x00, 0xff,
|
|
0x84, 0xb1, 0x05, 0x67, 0x72, 0x65, 0x65, 0x6e, // "green"
|
|
0xb4, 0xb3, 0x06, 0x43, 0x6f, 0x6c, 0x6f, 0x75, 0x72, 0xb0, 0x00, 0xb0, 0x02, 0x00, 0xff, 0xb0, 0x00,
|
|
0x84, 0x84, 0x87, 0x04, 0x41, 0x45, 0x85, 0x1f, // 12.345,
|
|
0x87, 0x08, 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);
|
|
}
|
|
}
|