Annotation skipping; text-syntax-like debug printing (plus pretty printing for free!!)

This commit is contained in:
Tony Garnock-Jones 2019-09-15 12:25:23 +01:00
parent 365e41b798
commit bec3a10d64
3 changed files with 102 additions and 15 deletions

View File

@ -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());
}
}

View File

@ -37,6 +37,7 @@ pub struct Decoder<R: Read> {
index: usize,
buf: Box<Option<Option<u8>>>,
placeholders: PlaceholderMap,
read_annotations: bool,
}
impl<R: Read> Decoder<R> {
@ -45,11 +46,16 @@ impl<R: Read> Decoder<R> {
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<R: Read> Decoder<R> {
}
pub fn skip(&mut self) -> Result<()> {
self.prime_if_possible()?;
self.prime()?;
*self.buf = None;
Ok(())
}
pub fn peek(&mut self) -> Result<u8> {
self.prime_if_possible()?;
self.prime()?;
match *self.buf {
Some(Some(v)) => Ok(v),
Some(None) => Err(Error::Eof),
@ -105,7 +111,7 @@ impl<R: Read> Decoder<R> {
}
pub fn readvalues(&mut self, mut count: usize) -> Result<Vec<AValue>> {
let mut pieces: Vec<AValue> = Vec::new();
let mut pieces: Vec<AValue> = Vec::with_capacity(count);
while count > 0 {
pieces.push(self.next()?);
count = count - 1;
@ -113,12 +119,15 @@ impl<R: Read> Decoder<R> {
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<usize> {
@ -225,10 +234,19 @@ impl<R: Read> Decoder<R> {
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) => {

View File

@ -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<AValue>, pub Value);
/// Single-precision IEEE 754 Value
@ -180,6 +180,58 @@ impl From<Vec<u8>> for Value { fn from(v: Vec<u8>) -> Self { Value::ByteString(v
impl From<Vec<AValue>> for Value { fn from(v: Vec<AValue>) -> 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 {