396 lines
17 KiB
Rust
396 lines
17 KiB
Rust
pub mod value;
|
|
pub mod symbol;
|
|
|
|
#[cfg(test)]
|
|
mod dom {
|
|
use super::value::{Value, PlainValue, NestedValue, Domain, Encoder, Codec};
|
|
|
|
#[derive(Debug, Hash, Clone, Ord, PartialEq, Eq, PartialOrd)]
|
|
pub enum Dom {
|
|
One,
|
|
Two,
|
|
}
|
|
|
|
impl Domain for Dom {
|
|
fn encode<'a, 'b, W: std::io::Write, N: NestedValue<Self>>(
|
|
&self, enc: &mut Encoder<'a, 'b, W, N, Self>) ->
|
|
super::value::encoder::Result
|
|
{
|
|
match self {
|
|
Dom::One => enc.write_all(&[255, 255, 255, 255]),
|
|
Dom::Two => enc.write(&self.as_preserves()?)
|
|
}
|
|
}
|
|
|
|
fn as_preserves<N: NestedValue<Self>>(&self) -> Result<N, std::io::Error> {
|
|
Ok(Value::symbol(&format!("Dom::{:?}", self)).wrap())
|
|
}
|
|
}
|
|
|
|
#[test] fn test_one() {
|
|
let v: PlainValue<_> = Value::from(vec![Value::from(1).wrap(),
|
|
Value::Domain(Dom::One).wrap(),
|
|
Value::from(2).wrap()])
|
|
.wrap();
|
|
assert_eq!(Codec::without_placeholders().encode_bytes(&v).unwrap(),
|
|
[147, 49, 255, 255, 255, 255, 50]);
|
|
}
|
|
|
|
#[test] fn test_two() {
|
|
let v: PlainValue<_> = Value::from(vec![Value::from(1).wrap(),
|
|
Value::Domain(Dom::Two).wrap(),
|
|
Value::from(2).wrap()])
|
|
.wrap();
|
|
assert_eq!(Codec::without_placeholders().encode_bytes(&v).unwrap(),
|
|
[147, 49, 120, 68, 111, 109, 58, 58, 84, 119, 111, 50]);
|
|
}
|
|
|
|
#[test] fn test_unit() {
|
|
let v: PlainValue<_> = Value::from(vec![Value::from(1).wrap(),
|
|
Value::Domain(()).wrap(),
|
|
Value::from(2).wrap()])
|
|
.wrap();
|
|
let e = Codec::without_placeholders().encode_bytes(&v).err().unwrap();
|
|
assert_eq!(e.kind(), std::io::ErrorKind::InvalidData);
|
|
assert_eq!(e.to_string(), "Cannot Preserves-encode domain-specific value ()");
|
|
}
|
|
}
|
|
|
|
#[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>, Dom> { Value::from(val) }
|
|
fn d(val: f64) -> Value<PlainValue<Dom>, 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};
|
|
use num::bigint::BigInt;
|
|
use super::dom::Dom;
|
|
|
|
type VV = Value<PlainValue<Dom>, 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_float());
|
|
*(f.as_float_mut().unwrap()) = 123.45;
|
|
assert_eq!(f, VV::from(123.45f32));
|
|
assert_eq!(f.as_float().unwrap(), 123.45f32);
|
|
}
|
|
|
|
#[test] fn double_mut() {
|
|
let mut f = VV::from(1.0);
|
|
assert!(f.is_double());
|
|
*(f.as_double_mut().unwrap()) = 123.45;
|
|
assert_eq!(f, VV::from(123.45));
|
|
assert_eq!(f.as_double().unwrap(), 123.45);
|
|
}
|
|
|
|
#[test] fn signedinteger_mut() {
|
|
let mut i = VV::from(123);
|
|
assert!(i.is_signedinteger());
|
|
*(i.as_signedinteger_mut().unwrap()) = BigInt::from(234);
|
|
assert_eq!(i, VV::from(234));
|
|
|
|
use num::traits::cast::ToPrimitive;
|
|
assert_eq!(i.as_signedinteger().unwrap().to_i64().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(says.clone(), vec![VV::from("Tony").wrap(), VV::from("Hello!").wrap()]);
|
|
r.as_record_mut().unwrap().1[0] = VV::from("Alice").wrap();
|
|
assert_eq!(r, VV::record(says, vec![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::Decoder;
|
|
use crate::value::{Value, PlainValue, NestedValue};
|
|
use super::dom::Dom;
|
|
|
|
#[test] fn read_123() {
|
|
let mut buf = &b"abc"[..];
|
|
let mut d = Decoder::<_, PlainValue<Dom>, Dom>::new(&mut buf, None);
|
|
assert_eq!(d.read().ok(), Some(97));
|
|
assert_eq!(d.read().ok(), Some(98));
|
|
assert_eq!(d.read().ok(), Some(99));
|
|
assert!(d.read().err().unwrap().is_eof())
|
|
}
|
|
|
|
#[test] fn skip_annotations_noskip() {
|
|
let mut buf = &b"\x0521"[..];
|
|
let mut d = Decoder::<_, PlainValue<Dom>, Dom>::new(&mut buf, None);
|
|
let v = d.next().unwrap();
|
|
assert_eq!(v.annotations().len(), 1);
|
|
assert_eq!(v.annotations()[0], Value::from(2).wrap());
|
|
assert_eq!(v.value(), &Value::from(1));
|
|
}
|
|
|
|
#[test] fn skip_annotations_skip() {
|
|
let mut buf = &b"\x0521"[..];
|
|
let mut d = Decoder::<_, PlainValue<Dom>, Dom>::new(&mut buf, None);
|
|
d.set_read_annotations(false);
|
|
let v = d.next().unwrap();
|
|
assert_eq!(v.annotations().len(), 0);
|
|
assert_eq!(v.value(), &Value::from(1));
|
|
}
|
|
|
|
#[test] fn two_values_at_once() {
|
|
let mut buf = &b"\x81tPing\x81tPong"[..];
|
|
assert_eq!(buf.len(), 12);
|
|
let mut d = Decoder::<_, PlainValue<Dom>, Dom>::new(&mut buf, None);
|
|
assert_eq!(d.next().unwrap().value(), &Value::simple_record("Ping", vec![]));
|
|
assert_eq!(d.next().unwrap().value(), &Value::simple_record("Pong", vec![]));
|
|
assert_eq!(buf.len(), 0);
|
|
}
|
|
|
|
#[test] fn buf_advanced() {
|
|
let mut buf = &b"\x81tPing\x81tPong"[..];
|
|
assert_eq!(buf.len(), 12);
|
|
let mut d = Decoder::<_, PlainValue<Dom>, Dom>::new(&mut buf, None);
|
|
assert_eq!(d.next().unwrap().value(), &Value::simple_record("Ping", vec![]));
|
|
assert_eq!(buf.len(), 6);
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod samples_tests {
|
|
use crate::symbol::Symbol;
|
|
use crate::value::{Codec, Decoder, decoder::Error};
|
|
use crate::value::{Value, PlainValue, Map};
|
|
use crate::value::DecodePlaceholderMap;
|
|
use crate::value::to_value;
|
|
use crate::value::from_value;
|
|
use super::dom::Dom;
|
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
struct ExpectedPlaceholderMapping(DecodePlaceholderMap<PlainValue<Dom>, Dom>);
|
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
struct TestCases {
|
|
decode_placeholders: ExpectedPlaceholderMapping,
|
|
tests: Map<Symbol, TestCase>
|
|
}
|
|
|
|
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
|
enum TestCase {
|
|
Test(#[serde(with = "serde_bytes")] Vec<u8>, PlainValue<Dom>),
|
|
NondeterministicTest(#[serde(with = "serde_bytes")] Vec<u8>, PlainValue<Dom>),
|
|
StreamingTest(#[serde(with = "serde_bytes")] Vec<u8>, PlainValue<Dom>),
|
|
DecodeTest(#[serde(with = "serde_bytes")] Vec<u8>, PlainValue<Dom>),
|
|
ParseError(String),
|
|
ParseShort(String),
|
|
DecodeError(#[serde(with = "serde_bytes")] Vec<u8>),
|
|
DecodeShort(#[serde(with = "serde_bytes")] Vec<u8>),
|
|
}
|
|
|
|
#[test] fn run() -> std::io::Result<()> {
|
|
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
|
|
let mut d = Decoder::<_, PlainValue<Dom>, Dom>::new(&mut fh, None);
|
|
let tests: TestCases = from_value(&d.next().unwrap()).unwrap();
|
|
// println!("{:#?}", tests);
|
|
|
|
let codec = Codec::new(tests.decode_placeholders.0);
|
|
for (Symbol(ref name), ref case) in tests.tests {
|
|
println!("{:?} ==> {:?}", name, case);
|
|
match case {
|
|
TestCase::Test(ref bin, ref val) => {
|
|
assert_eq!(&codec.decode(&mut &codec.encode_bytes(val)?[..])?, val);
|
|
assert_eq!(&codec.decode(&mut &bin[..])?, val);
|
|
assert_eq!(&codec.encode_bytes(val)?, bin);
|
|
}
|
|
TestCase::NondeterministicTest(ref bin, ref val) => {
|
|
// The test cases in samples.txt are carefully
|
|
// written so that while strictly
|
|
// "nondeterministic", the order of keys in
|
|
// dictionaries follows Preserves order.
|
|
assert_eq!(&codec.decode(&mut &codec.encode_bytes(val)?[..])?, val);
|
|
assert_eq!(&codec.decode(&mut &bin[..])?, val);
|
|
assert_eq!(&codec.encode_bytes(val)?, bin);
|
|
}
|
|
TestCase::StreamingTest(ref bin, ref val) => {
|
|
assert_eq!(&codec.decode(&mut &codec.encode_bytes(val)?[..])?, val);
|
|
assert_eq!(&codec.decode(&mut &bin[..])?, val);
|
|
}
|
|
TestCase::DecodeTest(ref bin, ref val) => {
|
|
assert_eq!(&codec.decode(&mut &codec.encode_bytes(val)?[..])?, val);
|
|
assert_eq!(&codec.decode(&mut &bin[..])?, val);
|
|
}
|
|
TestCase::ParseError(_) => (),
|
|
TestCase::ParseShort(_) => (),
|
|
TestCase::DecodeError(ref bin) => {
|
|
match codec.decode(&mut &bin[..]) {
|
|
Ok(_) => panic!("Unexpected success"),
|
|
Err(Error::Syntax(_)) => (),
|
|
Err(e) => panic!("Unexpected error {:?}", e),
|
|
}
|
|
}
|
|
TestCase::DecodeShort(ref bin) => {
|
|
match codec.decode(&mut &bin[..]) {
|
|
Ok(_) => panic!("Unexpected success"),
|
|
Err(Error::Eof) => (),
|
|
Err(e) => panic!("Unexpected error {:?}", e),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[test] fn simple_to_value() {
|
|
#[derive(Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
|
|
struct SimpleValue<'a>(String,
|
|
#[serde(with = "crate::symbol")] String,
|
|
Symbol,
|
|
&'a str,
|
|
#[serde(with = "serde_bytes")] &'a [u8],
|
|
#[serde(with = "serde_bytes")] Vec<u8>,
|
|
i16,
|
|
PlainValue<Dom>);
|
|
let v = SimpleValue("hello".to_string(),
|
|
"sym1".to_string(),
|
|
Symbol("sym2".to_string()),
|
|
"world",
|
|
&b"slice"[..],
|
|
b"vec".to_vec(),
|
|
12345,
|
|
Value::from("hi").wrap());
|
|
println!("{:#?}", v);
|
|
let w: PlainValue<Dom> = to_value(&v).unwrap();
|
|
println!("{:#?}", w);
|
|
let x = from_value(&w).unwrap();
|
|
println!("{:#?}", &x);
|
|
assert_eq!(v, x);
|
|
}
|
|
}
|