From ef3b88147e08c2c0b06e74e9953da53feb605e10 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Tue, 17 Sep 2019 11:27:44 +0100 Subject: [PATCH] Codec; implement Rust tests; samples.txt in quasi-canonical serialized order --- implementations/rust/src/lib.rs | 56 ++++++++++++++++++---- implementations/rust/src/symbol.rs | 12 +++++ implementations/rust/src/value/codec.rs | 41 ++++++++++++++++ implementations/rust/src/value/decoder.rs | 12 ++--- implementations/rust/src/value/encoder.rs | 15 +++--- implementations/rust/src/value/mod.rs | 2 + tests/samples.bin | Bin 5679 -> 5679 bytes tests/samples.txt | 42 ++++++++-------- 8 files changed, 135 insertions(+), 45 deletions(-) create mode 100644 implementations/rust/src/value/codec.rs diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index 0165c58..d757ee9 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -207,12 +207,11 @@ mod decoder_tests { #[cfg(test)] mod samples_tests { use crate::symbol::Symbol; - use crate::value::Decoder; + use crate::value::{Codec, Decoder, codec}; use crate::value::{Value, AValue}; use crate::value::DecodePlaceholderMap; use crate::value::to_value; use crate::value::from_value; - use crate::value::invert_map; use std::collections::BTreeMap; #[derive(Debug, serde::Serialize, serde::Deserialize)] @@ -235,20 +234,58 @@ mod samples_tests { DecodeShort(#[serde(with = "serde_bytes")] Vec), } - #[test] fn run() { + #[test] fn run() -> codec::Result<()> { let mut d = Decoder::new(std::fs::File::open("../../tests/samples.bin").unwrap(), None); let tests: TestCases = from_value(&d.next().unwrap()).unwrap(); - let decode_placeholders = tests.decode_placeholders.0; - let encode_placeholders = invert_map(&decode_placeholders); - // println!("{:#?}", tests); - println!("{:#?}", decode_placeholders); - println!("{:#?}", encode_placeholders); + + 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(&codec.encode_bytes(val)?[..])?, val); + assert_eq!(&codec.decode(&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(&codec.encode_bytes(val)?[..])?, val); + assert_eq!(&codec.decode(&bin[..])?, val); + assert_eq!(&codec.encode_bytes(val)?, bin); + } + TestCase::StreamingTest(ref bin, ref val) => { + assert_eq!(&codec.decode(&codec.encode_bytes(val)?[..])?, val); + assert_eq!(&codec.decode(&bin[..])?, val); + } + TestCase::ParseError(_) => (), + TestCase::ParseShort(_) => (), + TestCase::DecodeError(ref bin) => { + match codec.decode(&bin[..]) { + Ok(_) => panic!("Unexpected success"), + Err(codec::Error::Syntax(_)) => (), + Err(e) => panic!("Unexpected error {:?}", e), + } + } + TestCase::DecodeShort(ref bin) => { + match codec.decode(&bin[..]) { + Ok(_) => panic!("Unexpected success"), + Err(codec::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], @@ -256,7 +293,8 @@ mod samples_tests { i16, AValue); let v = SimpleValue("hello".to_string(), - Symbol("sym".to_string()), + "sym1".to_string(), + Symbol("sym2".to_string()), "world", &b"slice"[..], b"vec".to_vec(), diff --git a/implementations/rust/src/symbol.rs b/implementations/rust/src/symbol.rs index dbe8e4f..41f1bad 100644 --- a/implementations/rust/src/symbol.rs +++ b/implementations/rust/src/symbol.rs @@ -16,3 +16,15 @@ impl<'de> serde::Deserialize<'de> for Symbol { Ok(Symbol(s.clone())) } } + +pub fn serialize(s: &str, serializer: S) -> Result where S: serde::Serializer { + use serde::Serialize; + Symbol(s.to_string()).serialize(serializer) +} + +pub fn deserialize<'de, D>(deserializer: D) -> + Result where D: serde::Deserializer<'de> +{ + use serde::Deserialize; + Symbol::deserialize(deserializer).map(|v| v.0) +} diff --git a/implementations/rust/src/value/codec.rs b/implementations/rust/src/value/codec.rs new file mode 100644 index 0000000..eb24cda --- /dev/null +++ b/implementations/rust/src/value/codec.rs @@ -0,0 +1,41 @@ +use crate::value::{decoder, encoder, invert_map, AValue}; +use decoder::{Decoder, DecodePlaceholderMap}; +use encoder::{Encoder, EncodePlaceholderMap}; +use std::io::{Read, Write}; + +pub type Error = decoder::Error; +pub type Result = decoder::Result; + +pub struct Codec { + pub decode_placeholders: Option, + pub encode_placeholders: Option, +} + +impl Codec { + pub fn new(decode_placeholders: DecodePlaceholderMap) -> Self { + let encode_placeholders = Some(invert_map(&decode_placeholders)); + Codec { decode_placeholders: Some(decode_placeholders), encode_placeholders } + } + + pub fn without_placeholders() -> Self { + Codec { decode_placeholders: None, encode_placeholders: None } + } + + pub fn decoder<'a, R: Read>(&'a self, read: R) -> Decoder<'a, R> { + Decoder::new(read, self.decode_placeholders.as_ref()) + } + + pub fn encoder<'a, 'w, W: Write>(&'a self, write: &'w mut W) -> Encoder<'w, 'a, W> { + Encoder::new(write, self.encode_placeholders.as_ref()) + } + + pub fn decode(&self, read: R) -> Result { + self.decoder(read).next() + } + + pub fn encode_bytes(&self, v: &AValue) -> Result> { + let mut buf: Vec = Vec::new(); + self.encoder(&mut buf).write(v)?; + Ok(buf) + } +} diff --git a/implementations/rust/src/value/decoder.rs b/implementations/rust/src/value/decoder.rs index bdff2ac..766d119 100644 --- a/implementations/rust/src/value/decoder.rs +++ b/implementations/rust/src/value/decoder.rs @@ -40,21 +40,21 @@ impl Error { pub type DecodePlaceholderMap = std::collections::BTreeMap; -pub struct Decoder { +pub struct Decoder<'a, R: Read> { read: R, index: usize, buf: Box>>, - placeholders: DecodePlaceholderMap, + placeholders: Option<&'a DecodePlaceholderMap>, read_annotations: bool, } -impl Decoder { - pub fn new(read: R, placeholders: Option) -> Self { +impl<'a, R: Read> Decoder<'a, R> { + pub fn new(read: R, placeholders: Option<&'a DecodePlaceholderMap>) -> Self { Decoder{ read, index: 0, buf: Box::new(None), - placeholders: placeholders.unwrap_or(DecodePlaceholderMap::new()), + placeholders, read_annotations: true, } } @@ -254,7 +254,7 @@ impl Decoder { (Op::Misc(0), _) => Err(Error::Syntax("Invalid format A encoding")), (Op::Misc(1), arg) => { let n = self.wirelength(arg)?; - match self.placeholders.get(&n) { + match self.placeholders.and_then(|m| m.get(&n)) { Some(v) => Ok(v.clone().wrap()), None => Err(Error::Syntax("Invalid Preserves placeholder")), } diff --git a/implementations/rust/src/value/encoder.rs b/implementations/rust/src/value/encoder.rs index e41504b..53fe0c5 100644 --- a/implementations/rust/src/value/encoder.rs +++ b/implementations/rust/src/value/encoder.rs @@ -9,17 +9,14 @@ pub type Result = std::result::Result<(), Error>; pub type EncodePlaceholderMap = std::collections::BTreeMap; -pub struct Encoder<'a, W: Write> { +pub struct Encoder<'a, 'b, W: Write> { write: &'a mut W, - placeholders: EncodePlaceholderMap, + placeholders: Option<&'b EncodePlaceholderMap>, } -impl<'a, W: Write> Encoder<'a, W> { - pub fn new(write: &'a mut W, placeholders: Option) -> Self { - Encoder{ - write, - placeholders: placeholders.unwrap_or(EncodePlaceholderMap::new()), - } +impl<'a, 'b, W: Write> Encoder<'a, 'b, W> { + pub fn new(write: &'a mut W, placeholders: Option<&'b EncodePlaceholderMap>) -> Self { + Encoder{ write, placeholders } } pub fn _write(&mut self, v: u8) -> Result { @@ -82,7 +79,7 @@ impl<'a, W: Write> Encoder<'a, W> { } pub fn write_value(&mut self, v: &Value) -> Result { - match self.placeholders.get(v) { + match self.placeholders.and_then(|m| m.get(v)) { Some(&n) => self.write_header(Op::Misc(1), n), None => match v { Value::Boolean(false) => self.write_op(Op::Misc(0), 0), diff --git a/implementations/rust/src/value/mod.rs b/implementations/rust/src/value/mod.rs index f74c613..e62cbfb 100644 --- a/implementations/rust/src/value/mod.rs +++ b/implementations/rust/src/value/mod.rs @@ -1,3 +1,4 @@ +pub mod codec; pub mod constants; pub mod de; pub mod decoder; @@ -6,6 +7,7 @@ pub mod error; pub mod ser; pub mod value; +pub use codec::Codec; pub use de::Deserializer; pub use de::from_value; pub use decoder::DecodePlaceholderMap; diff --git a/tests/samples.bin b/tests/samples.bin index 77fd23cdc5f88333fe62af249321a97ba67c0ebb..cf9435d4428c6fb76bb12fd802d7fe286c524916 100644 GIT binary patch delta 204 zcmZ3lvtDPyRJOn*#==CyjkDi#PA=ru5{V4SD9ugEOU%sK7Uq$fnVwPNSUY(mmkvj0 zcxFmThGWX)E-o2P2*-(8VX`9kInHp$l$4^>;^KhGY`k(p5k83}nI)wusmu;ekJK9G zdIn8a=23HvEGSA%&MeN%&kL@~EZ8pq*A(KMSyCAp9O~y68RqEY8t$B5npaX(85A0f ZY|{F~5@ delta 202 zcmZ3lvtDPyRJOuI!@wlQjkDi#PX5Cs!yOrtQJR~SmzbHeZSn~&9l dict0: - dict1: + dict1: dict2: @"Missing close brace" dict2a: @"Missing close brace" dict3: @"Duplicate key" @@ -197,26 +197,26 @@ rfc8259-example1: rfc8259-example2: