diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index 3f5b70f..afc2dff 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -253,8 +253,8 @@ mod decoder_tests { let mut buf = &b"\x0521"[..]; let mut d = decoder::from_bytes(&mut buf); let v = d.demand_next().unwrap(); - assert_eq!(v.annotations().len(), 1); - assert_eq!(v.annotations()[0], Value::from(2).wrap()); + assert_eq!(v.annotations().slice().len(), 1); + assert_eq!(v.annotations().slice()[0], Value::from(2).wrap()); assert_eq!(v.value(), &Value::from(1)); } @@ -263,7 +263,7 @@ mod decoder_tests { let mut d = decoder::from_bytes(&mut buf); d.set_read_annotations(false); let v = d.demand_next().unwrap(); - assert_eq!(v.annotations().len(), 0); + assert_eq!(v.annotations().slice().len(), 0); assert_eq!(v.value(), &Value::from(1)); } diff --git a/implementations/rust/src/value/encoder.rs b/implementations/rust/src/value/encoder.rs index 44916fc..abdf3f3 100644 --- a/implementations/rust/src/value/encoder.rs +++ b/implementations/rust/src/value/encoder.rs @@ -20,9 +20,12 @@ impl<'a, W: Writer> Encoder<'a, W> { } pub fn write(&mut self, v: &IOValue) -> Result { - for ann in v.annotations() { - self.write.write_annotation_prefix()?; - self.write(ann)?; + match v.annotations().maybe_slice() { + None => (), + Some(anns) => for ann in anns { + self.write.write_annotation_prefix()?; + self.write(ann)?; + } } self.write_value(v.value()) } diff --git a/implementations/rust/src/value/reader.rs b/implementations/rust/src/value/reader.rs index 9b547ff..56842c5 100644 --- a/implementations/rust/src/value/reader.rs +++ b/implementations/rust/src/value/reader.rs @@ -7,7 +7,7 @@ use std::io::{Read, Error}; use std::marker::PhantomData; use super::constants::{Op, InvalidOp, AtomMinor, CompoundMinor}; use super::signed_integer::SignedInteger; -use super::value::{Value, NestedValue, IOValue, FALSE, TRUE, Map, Set, Record}; +use super::value::{Value, NestedValue, IOValue, FALSE, TRUE, Map, Set, Record, Annotations}; use crate::error::{self, ExpectedKind, Received, is_eof_io_error, io_eof, io_syntax_error}; pub type IOResult = std::result::Result; @@ -592,8 +592,8 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for BinaryReader<'de, S> { annotations.push(self.demand_next(read_annotations)?.into_owned()); } let (existing_annotations, v) = self.demand_next(read_annotations)?.into_owned().pieces(); - annotations.extend(existing_annotations); - Cow::Owned(IOValue::wrap_ann(annotations, v)) + annotations.extend_from_slice(existing_annotations.slice()); + Cow::Owned(IOValue::wrap(Annotations::new(Some(annotations)), v)) } else { self.skip_value()?; continue; diff --git a/implementations/rust/src/value/value.rs b/implementations/rust/src/value/value.rs index 5df7630..43428de 100644 --- a/implementations/rust/src/value/value.rs +++ b/implementations/rust/src/value/value.rs @@ -6,6 +6,7 @@ use std::convert::TryFrom; use std::convert::TryInto; use std::fmt::Debug; use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; use std::ops::Index; use std::ops::IndexMut; use std::string::String; @@ -26,16 +27,15 @@ pub trait Domain: Sized + Debug + Clone + Eq + Hash + Ord { } pub trait NestedValue: Sized + Debug + Clone + Eq + Hash + Ord { - fn wrap(v: Value) -> Self; - fn wrap_ann(anns: Vec, v: Value) -> Self; + fn wrap(anns: Annotations, v: Value) -> Self; - fn annotations(&self) -> &[Self]; + fn annotations(&self) -> &Annotations; fn value(&self) -> &Value; - fn pieces(self) -> (Vec, Value); + fn pieces(self) -> (Annotations, Value); fn value_owned(self) -> Value; fn debug_fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - for ann in self.annotations() { + for ann in self.annotations().slice() { write!(f, "@{:?} ", ann)?; } self.value().fmt(f) @@ -45,8 +45,7 @@ pub trait NestedValue: Sized + Debug + Clone + Eq + Hash + Ord { where F: Fn(&D) -> Value { - M::wrap_ann(self.annotations().iter().map(|a| a.copy_via(f)).collect(), - self.value().copy_via(f)) + M::wrap(self.annotations().copy_via(f), self.value().copy_via(f)) } fn to_io_value(&self) -> IOValue { @@ -280,7 +279,7 @@ impl, D: Domain> Debug for Value { impl, D: Domain> Value { pub fn wrap(self) -> N { - N::wrap(self) + N::wrap(Annotations::empty(), self) } fn expected(&self, k: ExpectedKind) -> Error { @@ -802,10 +801,64 @@ pub fn deserialize_nested_value<'de, D, N, Dom: Domain>(deserializer: D) -> //--------------------------------------------------------------------------- +#[derive(Clone)] +pub struct Annotations, D: Domain>(Option>>, PhantomData); + +impl, D: Domain> Annotations { + pub fn empty() -> Self { + Annotations(None, + PhantomData) + } + + pub fn new(anns: Option>) -> Self { + Annotations(anns.and_then(|v| if v.is_empty() { None } else { Some(Box::new(v)) }), + PhantomData) + } + + pub fn maybe_slice(&self) -> Option<&[N]> { + match self.0 { + None => None, + Some(ref b) => Some(&&b[..]), + } + } + + pub fn slice(&self) -> &[N] { + self.maybe_slice().unwrap_or(&[]) + } + + pub fn modify(&mut self, f: F) -> &mut Self + where + F: FnOnce(&mut Vec) + { + let mut v: Vec = self.0.take().map_or_else(|| vec![], |b| *b); + f(&mut v); + self.0 = if v.is_empty() { None } else { Some(Box::new(v)) }; + self + } + + pub fn copy_via, E: Domain, F>(&self, f: &F) -> Annotations + where + F: Fn(&D) -> Value + { + match self.0 { + None => + Annotations(None, PhantomData), + Some(ref b) => + Annotations(Some(Box::new(b.iter().map(|a| a.copy_via(f)).collect())), PhantomData), + } + } +} + /// An possibly-annotated Value, with annotations (themselves /// possibly-annotated) in order of appearance. #[derive(Clone)] -pub struct AnnotatedValue, D: Domain>(pub Vec, pub Value); +pub struct AnnotatedValue, D: Domain>(pub Annotations, pub Value); + +impl, D: Domain> AnnotatedValue { + fn new(anns: Annotations, value: Value) -> Self { + AnnotatedValue(anns, value) + } +} impl, D: Domain> PartialEq for AnnotatedValue { fn eq(&self, other: &Self) -> bool { @@ -839,7 +892,7 @@ impl, D: Domain> Ord for AnnotatedValue { pub struct PlainValue(AnnotatedValue, D>); impl PlainValue { - pub fn annotations_mut(&mut self) -> &mut Vec { + pub fn annotations_mut(&mut self) -> &mut Annotations { &mut (self.0).0 } @@ -849,15 +902,11 @@ impl PlainValue { } impl NestedValue for PlainValue { - fn wrap(v: Value) -> Self { - Self::wrap_ann(Vec::new(), v) + fn wrap(anns: Annotations, v: Value) -> Self { + PlainValue(AnnotatedValue::new(anns, v)) } - fn wrap_ann(anns: Vec, v: Value) -> Self { - PlainValue(AnnotatedValue(anns, v)) - } - - fn annotations(&self) -> &[Self] { + fn annotations(&self) -> &Annotations { &(self.0).0 } @@ -865,7 +914,7 @@ impl NestedValue for PlainValue { &(self.0).1 } - fn pieces(self) -> (Vec, Value) { + fn pieces(self) -> (Annotations, Value) { let AnnotatedValue(anns, v) = self.0; (anns, v) } @@ -901,15 +950,11 @@ use std::rc::Rc; pub struct RcValue(Rc, D>>); impl NestedValue for RcValue { - fn wrap(v: Value) -> Self { - Self::wrap_ann(Vec::new(), v) + fn wrap(anns: Annotations, v: Value) -> Self { + RcValue(Rc::new(AnnotatedValue::new(anns, v))) } - fn wrap_ann(anns: Vec, v: Value) -> Self { - RcValue(Rc::new(AnnotatedValue(anns, v))) - } - - fn annotations(&self) -> &[Self] { + fn annotations(&self) -> &Annotations { &(self.0).0 } @@ -917,7 +962,7 @@ impl NestedValue for RcValue { &(self.0).1 } - fn pieces(self) -> (Vec, Value) { + fn pieces(self) -> (Annotations, Value) { match Rc::try_unwrap(self.0) { Ok(AnnotatedValue(anns, v)) => (anns, v), Err(r) => (r.0.clone(), r.1.clone()), @@ -955,15 +1000,11 @@ use std::sync::Arc; pub struct ArcValue(Arc, D>>); impl NestedValue for ArcValue { - fn wrap(v: Value) -> Self { - Self::wrap_ann(Vec::new(), v) + fn wrap(anns: Annotations, v: Value) -> Self { + ArcValue(Arc::new(AnnotatedValue::new(anns, v))) } - fn wrap_ann(anns: Vec, v: Value) -> Self { - ArcValue(Arc::new(AnnotatedValue(anns, v))) - } - - fn annotations(&self) -> &[Self] { + fn annotations(&self) -> &Annotations { &(self.0).0 } @@ -971,7 +1012,7 @@ impl NestedValue for ArcValue { &(self.0).1 } - fn pieces(self) -> (Vec, Value) { + fn pieces(self) -> (Annotations, Value) { match Arc::try_unwrap(self.0) { Ok(AnnotatedValue(anns, v)) => (anns, v), Err(r) => (r.0.clone(), r.1.clone()), @@ -1012,21 +1053,17 @@ pub struct IOValue(Arc>); pub type UnwrappedIOValue = Value; lazy_static! { - pub static ref FALSE: IOValue = IOValue(Arc::new(AnnotatedValue(Vec::new(), Value::Boolean(false)))); - pub static ref TRUE: IOValue = IOValue(Arc::new(AnnotatedValue(Vec::new(), Value::Boolean(true)))); - pub static ref EMPTY_SEQ: IOValue = IOValue(Arc::new(AnnotatedValue(Vec::new(), Value::Sequence(Vec::new())))); + pub static ref FALSE: IOValue = IOValue(Arc::new(AnnotatedValue(Annotations::empty(), Value::Boolean(false)))); + pub static ref TRUE: IOValue = IOValue(Arc::new(AnnotatedValue(Annotations::empty(), Value::Boolean(true)))); + pub static ref EMPTY_SEQ: IOValue = IOValue(Arc::new(AnnotatedValue(Annotations::empty(), Value::Sequence(Vec::new())))); } impl NestedValue for IOValue { - fn wrap(v: Value) -> Self { - Self::wrap_ann(Vec::new(), v) + fn wrap(anns: Annotations, v: Value) -> Self { + IOValue(Arc::new(AnnotatedValue::new(anns, v))) } - fn wrap_ann(anns: Vec, v: Value) -> Self { - IOValue(Arc::new(AnnotatedValue(anns, v))) - } - - fn annotations(&self) -> &[Self] { + fn annotations(&self) -> &Annotations { &(self.0).0 } @@ -1034,7 +1071,7 @@ impl NestedValue for IOValue { &(self.0).1 } - fn pieces(self) -> (Vec, Value) { + fn pieces(self) -> (Annotations, Value) { match Arc::try_unwrap(self.0) { Ok(AnnotatedValue(anns, v)) => (anns, v), Err(r) => (r.0.clone(), r.1.clone()),