From bec3a10d641b1983fff2697447f4653dd855ea39 Mon Sep 17 00:00:00 2001 From: Tony Garnock-Jones Date: Sun, 15 Sep 2019 12:25:23 +0100 Subject: [PATCH] Annotation skipping; text-syntax-like debug printing (plus pretty printing for free!!) --- implementations/rust/src/lib.rs | 19 ++++++++- implementations/rust/src/value/codec.rs | 42 +++++++++++++------ implementations/rust/src/value/value.rs | 56 ++++++++++++++++++++++++- 3 files changed, 102 insertions(+), 15 deletions(-) diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index 46d58dd..b23ef1a 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -176,6 +176,7 @@ mod value_tests { #[cfg(test)] mod decoder_tests { use crate::value::codec::Decoder; + use crate::value::value::Value; #[test] fn read_123() { let mut d = Decoder::new(&b"abc"[..], None); @@ -185,8 +186,24 @@ mod decoder_tests { assert!(d.read().err().unwrap().is_eof()) } + #[test] fn skip_annotations_noskip() { + let mut d = Decoder::new(&b"\x0521"[..], None); + let v = d.next().ok().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 d = Decoder::new(&b"\x0521"[..], None); + d.set_read_annotations(false); + let v = d.next().ok().unwrap(); + assert_eq!(v.annotations().len(), 0); + assert_eq!(v.value(), &Value::from(1)); + } + #[test] fn read_samples() { let mut d = Decoder::new(std::fs::File::open("../../tests/samples.bin").unwrap(), None); - println!("{:?}", d.next().ok().unwrap()); + println!("{:#?}", d.next().ok().unwrap()); } } diff --git a/implementations/rust/src/value/codec.rs b/implementations/rust/src/value/codec.rs index a9c0613..d300dab 100644 --- a/implementations/rust/src/value/codec.rs +++ b/implementations/rust/src/value/codec.rs @@ -37,6 +37,7 @@ pub struct Decoder { index: usize, buf: Box>>, placeholders: PlaceholderMap, + read_annotations: bool, } impl Decoder { @@ -45,11 +46,16 @@ impl Decoder { read, index: 0, buf: Box::new(None), - placeholders: placeholders.unwrap_or(PlaceholderMap::new()) + placeholders: placeholders.unwrap_or(PlaceholderMap::new()), + read_annotations: true, } } - fn prime_if_possible(&mut self) -> Result<()> { + pub fn set_read_annotations(&mut self, read_annotations: bool) -> () { + self.read_annotations = read_annotations + } + + fn prime(&mut self) -> Result<()> { match *self.buf { None => { let bs = &mut [0]; @@ -68,13 +74,13 @@ impl Decoder { } pub fn skip(&mut self) -> Result<()> { - self.prime_if_possible()?; + self.prime()?; *self.buf = None; Ok(()) } pub fn peek(&mut self) -> Result { - self.prime_if_possible()?; + self.prime()?; match *self.buf { Some(Some(v)) => Ok(v), Some(None) => Err(Error::Eof), @@ -105,7 +111,7 @@ impl Decoder { } pub fn readvalues(&mut self, mut count: usize) -> Result> { - let mut pieces: Vec = Vec::new(); + let mut pieces: Vec = Vec::with_capacity(count); while count > 0 { pieces.push(self.next()?); count = count - 1; @@ -113,12 +119,15 @@ impl Decoder { Ok(pieces) } - pub fn nextop(&mut self) -> Result<(u8, u8, u8)> { - let b = self.read()?; + pub fn decodeop(b: u8) -> (u8, u8, u8) { let major = b >> 6; let minor = (b >> 4) & 3; let arg = b & 15; - Ok((major, minor, arg)) + (major, minor, arg) + } + + pub fn nextop(&mut self) -> Result<(u8, u8, u8)> { + Ok(Self::decodeop(self.read()?)) } pub fn varint(&mut self) -> Result { @@ -225,10 +234,19 @@ impl Decoder { Ok(Value::from(f64::from_bits(u64::from_be_bytes(bs.try_into().unwrap()))).wrap()) } (0, 0, 5) => { - let a = self.next()?; - let mut v = self.next()?; - v.annotations_mut().push(a); - Ok(v) + if self.read_annotations { + let mut annotations = vec![self.next()?]; + while Self::decodeop(self.peek()?) == (0, 0, 5) { + self.skip()?; + annotations.push(self.next()?); + } + let mut v = self.next()?; + v.annotations_mut().extend(annotations); + Ok(v) + } else { + self.next()?; + self.next() + } } (0, 0, _) => Err(Error::Syntax("Invalid format A encoding")), (0, 1, arg) => { diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index 28c7def..0c6aae0 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -10,7 +10,7 @@ use std::ops::Index; use std::ops::IndexMut; /// The `Value`s from the specification. -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum Value { Boolean(bool), Float(Float), @@ -27,7 +27,7 @@ pub enum Value { /// An possibly-annotated Value, with annotations (themselves /// possibly-annotated) in order of appearance. -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct AValue(pub Vec, pub Value); /// Single-precision IEEE 754 Value @@ -180,6 +180,58 @@ impl From> for Value { fn from(v: Vec) -> Self { Value::ByteString(v impl From> for Value { fn from(v: Vec) -> Self { Value::Sequence(v) } } +impl std::fmt::Debug for Value { + // Not *quite* a formatter for the Preserves text syntax, since it + // doesn't escape strings/symbols properly. + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Value::Boolean(true) => f.write_str("#true"), + Value::Boolean(false) => f.write_str("#false"), + Value::Float(Float(v)) => write!(f, "{:?}f", v), + Value::Double(Double(v)) => write!(f, "{:?}", v), + Value::SignedInteger(v) => write!(f, "{}", v), + Value::String(ref v) => write!(f, "{:?}", v), // TODO: proper escaping! + Value::ByteString(ref v) => { + f.write_str("#hex{")?; + for b in v { write!(f, "{:02x}", b)? } + f.write_str("}") + } + Value::Symbol(ref v) => { + // TODO: proper escaping! + if v.len() == 0 { + f.write_str("||") + } else { + write!(f, "{}", v) + } + } + Value::Record((ref l, ref fs)) => { + f.write_str("<")?; + l.fmt(f)?; + for v in fs { + f.write_str(" ")?; + v.fmt(f)?; + } + f.write_str(">") + } + Value::Sequence(ref v) => v.fmt(f), + Value::Set(ref v) => { + f.write_str("#set")?; + f.debug_set().entries(v.iter()).finish() + } + Value::Dictionary (ref v) => f.debug_map().entries(v.iter()).finish() + } + } +} + +impl std::fmt::Debug for AValue { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + for ann in &self.0 { + write!(f, "@{:?} ", ann)?; + } + self.1.fmt(f) + } +} + //--------------------------------------------------------------------------- impl AValue {