Codec; implement Rust tests; samples.txt in quasi-canonical serialized order

This commit is contained in:
Tony Garnock-Jones 2019-09-17 11:27:44 +01:00
parent 199ce1fdba
commit ef3b88147e
8 changed files with 135 additions and 45 deletions

View File

@ -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<u8>),
}
#[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(),

View File

@ -16,3 +16,15 @@ impl<'de> serde::Deserialize<'de> for Symbol {
Ok(Symbol(s.clone()))
}
}
pub fn serialize<S>(s: &str, serializer: S) -> Result<S::Ok, S::Error> where S: serde::Serializer {
use serde::Serialize;
Symbol(s.to_string()).serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) ->
Result<String, D::Error> where D: serde::Deserializer<'de>
{
use serde::Deserialize;
Symbol::deserialize(deserializer).map(|v| v.0)
}

View File

@ -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<T> = decoder::Result<T>;
pub struct Codec {
pub decode_placeholders: Option<DecodePlaceholderMap>,
pub encode_placeholders: Option<EncodePlaceholderMap>,
}
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<R: Read>(&self, read: R) -> Result<AValue> {
self.decoder(read).next()
}
pub fn encode_bytes(&self, v: &AValue) -> Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
self.encoder(&mut buf).write(v)?;
Ok(buf)
}
}

View File

@ -40,21 +40,21 @@ impl Error {
pub type DecodePlaceholderMap = std::collections::BTreeMap<usize, Value>;
pub struct Decoder<R: Read> {
pub struct Decoder<'a, R: Read> {
read: R,
index: usize,
buf: Box<Option<Option<u8>>>,
placeholders: DecodePlaceholderMap,
placeholders: Option<&'a DecodePlaceholderMap>,
read_annotations: bool,
}
impl<R: Read> Decoder<R> {
pub fn new(read: R, placeholders: Option<DecodePlaceholderMap>) -> 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<R: Read> Decoder<R> {
(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")),
}

View File

@ -9,17 +9,14 @@ pub type Result = std::result::Result<(), Error>;
pub type EncodePlaceholderMap = std::collections::BTreeMap<Value, usize>;
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<EncodePlaceholderMap>) -> 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),

View File

@ -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;

Binary file not shown.

View File

@ -32,7 +32,7 @@
bytes13: <Test #hex{6f 11 61 62 63 6c 34 f0 5c 2f 22 08 0c 0a 0d 09 78 79 7a} #"abc\x6c\x34\xf0\\/\"\b\f\n\r\txyz">
dict0: <Test #hex{b0} {}>
dict1: <NondeterministicTest #hex{b8 7161 31 5162 01 93313233 6163 b2 7a66697273742d6e616d65 59456c697a6162657468 b2 777375726e616d65 59426c61636b77656c6c} { a: 1 "b": #true [1 2 3]: #"c" { first-name: "Elizabeth" }: { surname: "Blackwell" } }>
dict1: <NondeterministicTest #hex{b8 5162 01 7161 31 93313233 6163 b2 7a66697273742d6e616d65 59456c697a6162657468 b2 777375726e616d65 59426c61636b77656c6c} { a: 1 "b": #true [1 2 3]: #"c" { first-name: "Elizabeth" }: { surname: "Blackwell" } }>
dict2: @"Missing close brace" <ParseShort "{ a: b, c: d ">
dict2a: @"Missing close brace" <ParseShort "{">
dict3: @"Duplicate key" <ParseError "{ a: 1, a: 2 }">
@ -197,26 +197,26 @@
rfc8259-example1: <NondeterministicTest
#hex{b2 55 496d616765
bc 55 5469746c65
5f14 566965772066726f6d203135746820466c6f6f72
59 5468756d626e61696c
b6 53 55726c
5f26 687474703a2f2f7777772e6578616d706c652e636f6d2f696d6167652f343831393839393433
56 486569676874
41 7d
55 5769647468
41 64
58 416e696d61746564
bc 58 416e696d61746564
75 66616c7365
56 486569676874
42 0258
55 5769647468
42 0320
53 494473
94 41 74
42 03af
42 00ea
43 009789}
43 009789
59 5468756d626e61696c
b6 56 486569676874
41 7d
53 55726c
5f26 687474703a2f2f7777772e6578616d706c652e636f6d2f696d6167652f343831393839393433
55 5769647468
41 64
55 5469746c65
5f14 566965772066726f6d203135746820466c6f6f72
55 5769647468
42 0320}
{
"Image": {
"Width": 800,
@ -233,22 +233,22 @@
}>
rfc8259-example2: <NondeterministicTest
#hex{92 bf10 58 4c61746974756465 03 4042e226809d4952
57 41646472657373 50
59 707265636973696f6e 53 7a6970
#hex{92 bf10 57 41646472657373 50
54 43697479 5d 53414e204652414e434953434f
57 436f756e747279 52 5553
58 4c61746974756465 03 4042e226809d4952
59 4c6f6e676974756465 03 c05e99566cf41f21
55 5374617465 52 4341
53 5a6970 55 3934313037
54 43697479 5d 53414e204652414e434953434f
bf10 58 4c61746974756465 03 4042af9d66adb403
57 41646472657373 50
59 707265636973696f6e 53 7a6970
bf10 57 41646472657373 50
54 43697479 59 53554e4e5956414c45
57 436f756e747279 52 5553
58 4c61746974756465 03 4042af9d66adb403
59 4c6f6e676974756465 03 c05e81aa4fca42af
55 5374617465 52 4341
53 5a6970 55 3934303835
54 43697479 59 53554e4e5956414c45}
59 707265636973696f6e 53 7a6970}
[
{
"precision": "zip",