diff --git a/implementations/rust/preserves/Cargo.toml b/implementations/rust/preserves/Cargo.toml index 92d8f3b..65419a3 100644 --- a/implementations/rust/preserves/Cargo.toml +++ b/implementations/rust/preserves/Cargo.toml @@ -13,7 +13,7 @@ gitlab = { repository = "preserves/preserves" } [dependencies] base64 = "0.13" -bytemuck = "1.12" +bytemuck = { version = "1.12", features = ["extern_crate_alloc"] } dtoa = "0.4" lazy_static = "1.4.0" num-bigint = "0.4" diff --git a/implementations/rust/preserves/src/error.rs b/implementations/rust/preserves/src/error.rs index 6cc0cf2..ef09674 100644 --- a/implementations/rust/preserves/src/error.rs +++ b/implementations/rust/preserves/src/error.rs @@ -6,7 +6,6 @@ use std::io; pub enum Error { Io(io::Error), Message(String), - InvalidUnicodeScalar(u32), NumberOutOfRange(BigInt), MissingCloseDelimiter, MissingItem, @@ -34,8 +33,6 @@ pub enum ExpectedKind { Embedded, - Option, - UnicodeScalar, Annotation, } diff --git a/implementations/rust/preserves/src/lib.rs b/implementations/rust/preserves/src/lib.rs index 4534777..b9dfa4d 100644 --- a/implementations/rust/preserves/src/lib.rs +++ b/implementations/rust/preserves/src/lib.rs @@ -3,53 +3,49 @@ pub mod domain; pub mod error; pub mod float; pub mod hex; -pub mod packed; +pub mod merge; +// pub mod packed; pub mod reader; pub mod repr; pub mod signed_integer; pub mod source; -pub mod text; +// pub mod text; pub mod types; pub mod writer; pub use domain::*; -pub use packed::PackedReader; -pub use packed::PackedWriter; -pub use packed::annotated_from_bytes; -pub use packed::annotated_iovalue_from_bytes; -pub use packed::from_bytes; -pub use packed::iovalue_from_bytes; +pub use error::Error; +pub use error::ExpectedKind; +pub use merge::merge; +pub use merge::merge2; +// pub use packed::PackedReader; +// pub use packed::PackedWriter; +// pub use packed::annotated_from_bytes; +// pub use packed::annotated_iovalue_from_bytes; +// pub use packed::from_bytes; +// pub use packed::iovalue_from_bytes; pub use reader::IOValues; pub use reader::Reader; pub use repr::Annotations; pub use repr::ArcValue; pub use repr::Atom; -pub use repr::Bytes; -pub use repr::Embedded; pub use repr::IOValue; pub use repr::Map; -pub use repr::PlainValue; pub use repr::NoValue; pub use repr::Record; pub use repr::Set; -pub use repr::Symbol; pub use repr::Value; pub use repr::ValueImpl; -pub use repr::copy_via; -pub use repr::iovalue; -pub use repr::owned; -pub use repr::shell; -pub use repr::value; pub use signed_integer::SignedInteger; pub use source::BinarySource; pub use source::BytesBinarySource; pub use source::IOBinarySource; -pub use text::TextReader; -pub use text::TextWriter; -pub use text::annotated_from_str; -pub use text::annotated_iovalue_from_str; -pub use text::from_str; -pub use text::iovalue_from_str; +// pub use text::TextReader; +// pub use text::TextWriter; +// pub use text::annotated_from_str; +// pub use text::annotated_iovalue_from_str; +// pub use text::from_str; +// pub use text::iovalue_from_str; pub use types::AtomClass; pub use types::CompoundClass; pub use types::ValueClass; @@ -64,45 +60,45 @@ mod demo { // d.get(&k) // } - #[test] fn a() { - let l: PlainValue = "label".parse().unwrap(); - let r = Record::new(l.value_clone(), vec![owned(1), owned(2), owned(3)]); - let r2 = Record::new(l, vec![owned(1), owned(2), owned(4)]); + // #[test] fn a() { + // let l: PlainValue = "label".parse().unwrap(); + // let r = Record::new(l.value_clone(), vec![owned(1), owned(2), owned(3)]); + // let r2 = Record::new(l, vec![owned(1), owned(2), owned(4)]); - let mut v: Map, PlainValue> = Map::new(); - v.insert("\"abc\"".parse().unwrap(), "def".parse().unwrap()); - v.insert("abc".parse().unwrap(), "DEF".parse().unwrap()); - v.insert(owned(123), "xyz".parse().unwrap()); - v.insert(owned(vec![1, 2, 3]), "{a: 1, b: 2}".parse().unwrap()); - v.insert(owned(r2), "bbb".parse().unwrap()); - v.insert(owned(r), "".parse().unwrap()); - let w: &dyn ValueImpl = &v; - println!("GETw abc {:?}", w.get(&"abc")); - println!("GETw 123 {:?}", w.get(&123)); - println!("GETw qqq {:?}", w.get(&"qqq")); - println!("GETv abc {:?}", v.get(&*value(&"abc"))); - println!("GETv 123 {:?}", v.get(&*value(&123))); - println!("GETv qqq {:?}", v.get(&*value(&"qqq"))); - for (kk, vv) in w.entries() { - println!("{:#?} ==> {:#?}", kk, vv); - } + // let mut v: Map, PlainValue> = Map::new(); + // v.insert("\"abc\"".parse().unwrap(), "def".parse().unwrap()); + // v.insert("abc".parse().unwrap(), "DEF".parse().unwrap()); + // v.insert(owned(123), "xyz".parse().unwrap()); + // v.insert(owned(vec![1, 2, 3]), "{a: 1, b: 2}".parse().unwrap()); + // v.insert(owned(r2), "bbb".parse().unwrap()); + // v.insert(owned(r), "".parse().unwrap()); + // let w: &dyn ValueImpl = &v; + // println!("GETw abc {:?}", w.get(&"abc")); + // println!("GETw 123 {:?}", w.get(&123)); + // println!("GETw qqq {:?}", w.get(&"qqq")); + // println!("GETv abc {:?}", v.get(&*value(&"abc"))); + // println!("GETv 123 {:?}", v.get(&*value(&123))); + // println!("GETv qqq {:?}", v.get(&*value(&"qqq"))); + // for (kk, vv) in w.entries() { + // println!("{:#?} ==> {:#?}", kk, vv); + // } - // { - // use std::io::BufRead; - // for line in std::io::stdin().lock().lines() { - // let line = line.unwrap(); - // let key = line.parse::>().unwrap(); - // let val = w.get(&key); - // println!("{:?} == {:?} ==> {:?} == {:?}", line, &key, val, getit(&v, &line)); - // } - // } - } + // // { + // // use std::io::BufRead; + // // for line in std::io::stdin().lock().lines() { + // // let line = line.unwrap(); + // // let key = line.parse::>().unwrap(); + // // let val = w.get(&key); + // // println!("{:?} == {:?} ==> {:?} == {:?}", line, &key, val, getit(&v, &line)); + // // } + // // } + // } - #[test] fn value_size() { - println!("Value size {}", std::mem::size_of::>()); - println!("&dyn ValueImpl size {}", std::mem::size_of::<&dyn ValueImpl>()); - println!("Box dyn ValueImpl size {}", std::mem::size_of::>>()); - } + // #[test] fn value_size() { + // println!("Value size {}", std::mem::size_of::>()); + // println!("&dyn ValueImpl size {}", std::mem::size_of::<&dyn ValueImpl>()); + // println!("Box dyn ValueImpl size {}", std::mem::size_of::>>()); + // } } #[cfg(test)] diff --git a/implementations/rust/preserves/src/merge.rs b/implementations/rust/preserves/src/merge.rs index 02761ba..afb4170 100644 --- a/implementations/rust/preserves/src/merge.rs +++ b/implementations/rust/preserves/src/merge.rs @@ -1,64 +1,89 @@ -use super::Map; -use super::NestedValue; -use super::Record; -use super::Value; +use crate::Annotations; +use crate::ArcValue; +use crate::CompoundClass; +use crate::Map; +use crate::Record; +use crate::Value; +use crate::ValueClass; +use crate::ValueImpl; -pub fn merge_seqs(mut a: Vec, mut b: Vec) -> Option> { +pub fn merge_seqs>( + mut a: Vec>, + mut b: Vec>, +) -> Option>> { if a.len() > b.len() { std::mem::swap(&mut a, &mut b); } let mut r = vec![]; let mut bi = b.into_iter(); for av in a.into_iter() { - r.push(merge2(av, bi.next().unwrap())?); + r.push(merge2(&*av, &*bi.next().unwrap())?); } - r.extend(bi); + r.extend(bi.map(|bv| bv.value_clone())); Some(r) } -pub fn merge2(v: N, w: N) -> Option { - let (mut v_anns, v_val) = v.pieces(); - let (w_anns, w_val) = w.pieces(); - match &mut v_anns { - None => v_anns = w_anns, - Some(vs) => match w_anns { - None => (), - Some(ws) => vs.extend(ws.into_iter()), +pub fn merge2>(v: &Value, w: &Value) -> Option> { + let anns = match (v.annotations(), w.annotations()) { + (Some(va), Some(wa)) => { + let mut a = va.to_vec(); + a.extend(wa.to_vec()); + a } - } - if v_val == w_val { - Some(N::wrap(v_anns, v_val)) + (Some(va), None) => va.to_vec(), + (None, Some(wa)) => wa.to_vec(), + (None, None) => vec![], + }; + + let r = if v == w { + Some(v.peeled().value_clone()) } else { - let maybe_merged = match v_val { - Value::Record(rv) => - Some(Value::Record(Record(merge_seqs(rv.0, w_val.into_record()?.0)?))), - Value::Sequence(vs) => - Some(Value::Sequence(merge_seqs(vs, w_val.into_sequence()?)?)), - Value::Set(_vs) => + match v.value_class() { + ValueClass::Atomic(_) => None, + ValueClass::Embedded => None, + ValueClass::Compound(CompoundClass::Record) => if w.is_record() { + todo!() + // Some(owned(Record::new(merge2(&*v.label(), &*w.label())?, + // merge_seqs(v.iter().collect(), w.iter().collect())?))) + } else { + None + } + ValueClass::Compound(CompoundClass::Sequence) => if w.is_sequence() { + Some(owned(merge_seqs(v.iter().collect(), w.iter().collect())?)) + } else { + None + } + ValueClass::Compound(CompoundClass::Set) => None, // unsure how to merge sets - Value::Dictionary(vs) => { - let mut ws = w_val.into_dictionary()?; + ValueClass::Compound(CompoundClass::Dictionary) => if w.is_dictionary() { + let mut ws: Map<_, _> = w.entries().collect(); let mut rs = Map::new(); - for (k, vv) in vs.into_iter() { + for (k, vv) in v.entries() { match ws.remove(&k) { - Some(wv) => { rs.insert(k, merge2(vv, wv)?); } - None => { rs.insert(k, vv); } + Some(wv) => { rs.insert(k.value_clone(), merge2(&*vv, &*wv)?); } + None => { rs.insert(k.value_clone(), vv.value_clone()); } } } - rs.extend(ws.into_iter()); - Some(Value::Dictionary(rs)) + rs.extend(ws.into_iter().map(|(k, wv)| (k.value_clone(), wv.value_clone()))); + Some(owned(rs)) + } else { + None } - _ => None, - }; - maybe_merged.map(|vw| N::wrap(v_anns, vw)) - } + } + }; + + r.map(|r| if anns.is_empty() { + r + } else { + owned(Annotations::new(r, anns)) + }) } -pub fn merge>(vs: I) -> Option { +pub fn merge>>(vs: I) -> Option> { let mut vs = vs.into_iter(); - let mut v = vs.next().expect("at least one value in merge()"); + let mut v = vs.next().expect("at least one value in merge()").value_clone(); for w in vs { - match merge2(v, w) { + match merge2(&*v, &*w) { Some(merged) => v = merged, None => return None, } diff --git a/implementations/rust/preserves/src/packed/mod.rs b/implementations/rust/preserves/src/packed/mod.rs index 55f1648..566519a 100644 --- a/implementations/rust/preserves/src/packed/mod.rs +++ b/implementations/rust/preserves/src/packed/mod.rs @@ -1,6 +1,6 @@ pub mod constants; pub mod reader; -pub mod view; +// pub mod view; pub mod writer; pub use reader::PackedReader; diff --git a/implementations/rust/preserves/src/packed/writer.rs b/implementations/rust/preserves/src/packed/writer.rs index ef2e75b..c4ebe1a 100644 --- a/implementations/rust/preserves/src/packed/writer.rs +++ b/implementations/rust/preserves/src/packed/writer.rs @@ -4,7 +4,7 @@ use std::convert::TryInto; use std::io; use std::io::Write; use super::constants::Tag; -use crate::{boundary as B, ValueImpl, Domain, DomainEncode, IOValue, IOValueDomainCodec, Writer}; +use crate::{boundary as B, ValueImpl, DomainEncode, IOValue, IOValueDomainCodec, Writer}; struct Buffers { base: W, @@ -36,9 +36,9 @@ pub struct PackedWriter(Buffers); impl PackedWriter<&mut Vec> { #[inline(always)] - pub fn encode>( + pub fn encode>( enc: &mut Enc, - v: &dyn ValueImpl, + v: &V, ) -> io::Result> { let mut buf: Vec = Vec::new(); v.write(&mut PackedWriter::new(&mut buf), enc)?; diff --git a/implementations/rust/preserves/src/repr.rs b/implementations/rust/preserves/src/repr.rs index 8055d7e..22e558a 100644 --- a/implementations/rust/preserves/src/repr.rs +++ b/implementations/rust/preserves/src/repr.rs @@ -1,6 +1,3 @@ -use bytemuck::TransparentWrapper; - -use std::borrow::Borrow; use std::borrow::Cow; use std::cmp::Ordering; use std::fmt::Debug; @@ -15,6 +12,7 @@ use std::vec::Vec; pub use std::collections::BTreeSet as Set; pub use std::collections::BTreeMap as Map; +use crate::signed_integer::OutOfRange; use crate::{AtomClass, TextWriter, DefaultDomainCodec, write_value}; use crate::CompoundClass; use crate::Domain; @@ -26,256 +24,106 @@ use crate::domain::{NoEmbeddedDomainCodec, DomainEncode, IOValueDomainCodec}; use super::float::{eq_f32, eq_f64, cmp_f32, cmp_f64}; -pub type PlainValue<'va, D = IOValue> = Box + 'va>; - -pub enum Value<'r, D: Domain = IOValue> { - Borrowed(&'r (dyn ValueImpl + 'r)), - Shell(PlainValue<'r, D>), - Owned(PlainValue<'static, D>), -} - -impl<'r, D: Domain> Value<'r, D> { - pub fn into_owned(self: Value<'r, D>) -> PlainValue<'static, D> { - match self { - Value::Borrowed(r) => r.value_clone(), - Value::Shell(v) => v.value_clone(), - Value::Owned(v) => v, - } - } -} - -impl<'r, 'va: 'r, D: Domain> From<&'r (dyn ValueImpl + 'r)> for Value<'r, D> { - fn from(r: &'r (dyn ValueImpl + 'r)) -> Self { - Value::Borrowed(r) - } -} - -impl<'r, D: Domain> From> for Value<'r, D> { - fn from(v: PlainValue<'static, D>) -> Self { - Value::Owned(v) - } -} - -impl<'r, D: Domain> Deref for Value<'r, D> { - type Target = dyn ValueImpl + 'r; - - fn deref(&self) -> &Self::Target { - match self { - Value::Borrowed(r) => r, - Value::Shell(v) => v, - Value::Owned(v) => v, - } - } -} - -impl<'r, D: Domain> From> for ArcValue { - fn from(v: Value<'r, D>) -> Self { - v.into_owned().into() - } -} - -impl<'r> From> for IOValue { - fn from(v: Value<'r, IOValue>) -> Self { - v.into_owned().into() - } -} - -impl<'r, 'va: 'r, D: Domain> Debug for Value<'r, D> { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.deref().fmt(f) - } -} - -impl<'r, 'va: 'r, D: Domain> PartialEq for Value<'r, D> { - fn eq(&self, other: &Self) -> bool { - &**self == &**other - } -} - -impl<'r, 'va: 'r, D: Domain> Eq for Value<'r, D> {} - -impl<'r, 'va: 'r, D: Domain> PartialOrd for Value<'r, D> { - fn partial_cmp(&self, other: &Self) -> Option { - Some((&**self).cmp(&**other)) - } -} - -impl<'r, 'va: 'r, D: Domain> Ord for Value<'r, D> { - fn cmp(&self, other: &Self) -> Ordering { - (&**self).cmp(&**other) - } -} - -impl<'r, 'va: 'r, D: Domain> Hash for Value<'r, D> { - fn hash(&self, state: &mut H) { - (&**self).hash(state) - } -} +#[repr(transparent)] +pub struct Value(pub V); /// Atomic values from the specification. -pub trait ValueImpl { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { +pub trait ValueImpl: Sized { + type Embedded: Domain; + type Mapped: ValueImpl; + type Items<'a>: Iterator> + 'a where Self: 'a; + type Entries<'a>: Iterator, &'a Value)> + 'a where Self: 'a; + + fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { write_value(w, self, enc) } - fn value_clone(&self) -> PlainValue<'static, D>; fn value_class(&self) -> ValueClass; - fn as_boolean(&self) -> Option { None } - fn as_float(&self) -> Option { None } - fn as_double(&self) -> Option { None } + fn as_boolean(&self) -> Option; + fn as_float(&self) -> Option; + fn as_double(&self) -> Option; + fn as_signed_integer(&self) -> Option>; + fn as_string(&self) -> Option>; + fn as_bytestring(&self) -> Option>; + fn as_symbol(&self) -> Option>; - fn is_signed_integer(&self) -> bool { false } - fn as_signed_integer(&self) -> Option { None } + fn as_i8(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_u8(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_i16(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_u16(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_i32(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_u32(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_i64(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_u64(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_i128(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_u128(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_isize(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } + fn as_usize(&self) -> Option> { self.as_signed_integer().map(|i| (&*i).try_into()) } - fn as_string(&self) -> Option> { None } - fn as_bytestring(&self) -> Option> { None } - fn as_symbol(&self) -> Option> { None } + fn is_record(&self) -> bool; + fn label(&self) -> Value; - fn is_record(&self) -> bool { false } - fn label(&self) -> Value<'_, D> { panic!("Not a record") } + fn is_sequence(&self) -> bool; + fn len(&self) -> usize; + fn index(&self, _i: usize) -> Value; + fn iter(&self) -> Self::Items<'_>; - fn is_sequence(&self) -> bool { false } - fn len(&self) -> usize { panic!("Has no length") } - fn index(&self, _i: usize) -> Value<'_, D> { panic!("Not indexable") } - fn iter(&self) -> Box> + '_> { panic!("Not iterable") } + fn is_set(&self) -> bool; + fn has>(&self, _v: &Value) -> bool; - fn is_set(&self) -> bool { false } - fn has(&self, _v: &dyn ValueImpl) -> bool { false } + fn is_dictionary(&self) -> bool; + fn get>(&self, _k: &Value) -> Option>; + fn entries(&self) -> Self::Entries<'_>; - fn is_dictionary(&self) -> bool { false } - fn get(&self, _k: &dyn ValueImpl) -> Option> { None } - fn entries(&self) -> Box, Value<'_, D>)> + '_> { panic!("Not a dictionary") } + fn as_embedded(&self) -> Option>; - fn is_embedded(&self) -> bool { false } - fn embedded(&self) -> Cow<'_, D> { panic!("Not an embedded value") } + // INVARIANT: return Some() *only* when the contained collection is nonempty + fn annotations(&self) -> Option>; - fn annotations(&self) -> Option> { None } + fn peeled(&self) -> &Self; + + fn copy(w: &Value, f: &mut F) -> Result, Err> + where + F: FnMut(&E::Embedded) -> Result, Err>; + + fn map_embedded(&self, f: &mut F) -> Result>, Err> + where + F: FnMut(&Self::Embedded) -> Result; } -pub fn value>(v: &V) -> Value<'_, D> { - Value::Borrowed(v) -} +impl Deref for Value { + type Target = V; -pub fn shell<'r, D: Domain, V: ValueImpl + 'r>(v: V) -> Value<'r, D> { - Value::Shell(Box::new(v)) -} - -pub fn owned<'va, D: Domain, V: ValueImpl + 'static>(v: V) -> PlainValue<'va, D> { - Box::new(v) -} - -pub fn arcvalue + 'static>(v: V) -> ArcValue { - ArcValue(Arc::new(v)) -} - -pub fn iovalue + 'static>(v: V) -> IOValue { - IOValue(arcvalue(v)) -} - -pub fn copy_via( - v: &dyn ValueImpl, - f: &mut F, -) -> Result, Err> -where - F: FnMut(&D) -> Result, Err> -{ - match v.value_class() { - ValueClass::Atomic(a) => Ok(match a { - AtomClass::Boolean => Box::new(v.as_boolean().unwrap()), - AtomClass::Float => Box::new(v.as_float().unwrap()), - AtomClass::Double => Box::new(v.as_double().unwrap()), - AtomClass::SignedInteger => Box::new(v.as_signed_integer().unwrap()), - AtomClass::String => Box::new(v.as_string().unwrap().into_owned()), - AtomClass::ByteString => Box::new(Bytes(v.as_bytestring().unwrap().into_owned())), - AtomClass::Symbol => Box::new(Symbol(v.as_symbol().unwrap().into_owned())), - }), - ValueClass::Compound(c) => Ok(match c { - CompoundClass::Sequence => - Box::new(v.iter().map(|w| copy_via(&*w, f)).collect::, _>>()?), - CompoundClass::Set => - Box::new(v.iter().map(|w| copy_via(&*w, f)).collect::, _>>()?), - CompoundClass::Record => - Box::new(Record::new( - copy_via(&*v.label(), f)?, - v.iter().map(|w| copy_via(&*w, f)).collect::, _>>()?)), - CompoundClass::Dictionary => - Box::new(v.entries().map(|(k, w)| Ok((copy_via(&*k, f)?, copy_via(&*w, f)?))) - .collect::, _>>()?), - }), - ValueClass::Embedded => f(&v.embedded()), + fn deref(&self) -> &Self::Target { + &self.0 } } -impl<'a, D: Domain> From<&'a dyn ValueImpl> for PlainValue<'static, D> { - fn from(v: &'a dyn ValueImpl) -> Self { - v.value_clone() +impl Clone for Value { + fn clone(&self) -> Self { + Value(self.0.clone()) } } -impl<'a, D: Domain, V: ValueImpl + ?Sized> ValueImpl for &'a V { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { (*self).write(w, enc) } - fn value_clone(&self) -> PlainValue<'static, D> { (*self).value_clone() } - fn value_class(&self) -> ValueClass { (*self).value_class() } - fn as_boolean(&self) -> Option { (*self).as_boolean() } - fn as_float(&self) -> Option { (*self).as_float() } - fn as_double(&self) -> Option { (*self).as_double() } - fn is_signed_integer(&self) -> bool { (*self).is_signed_integer() } - fn as_signed_integer(&self) -> Option { (*self).as_signed_integer() } - fn as_string(&self) -> Option> { (*self).as_string() } - fn as_bytestring(&self) -> Option> { (*self).as_bytestring() } - fn as_symbol(&self) -> Option> { (*self).as_symbol() } - fn is_record(&self) -> bool { (*self).is_record() } - fn label(&self) -> Value<'_, D> { (*self).label() } - fn is_sequence(&self) -> bool { (*self).is_sequence() } - fn len(&self) -> usize { (*self).len() } - fn index(&self, i: usize) -> Value<'_, D> { (*self).index(i) } - fn iter(&self) -> Box> + '_> { (*self).iter() } - fn is_set(&self) -> bool { (*self).is_set() } - fn has(&self, v: &dyn ValueImpl) -> bool { (*self).has(v) } - fn is_dictionary(&self) -> bool { (*self).is_dictionary() } - fn get(&self, k: &dyn ValueImpl) -> Option> { (*self).get(k) } - fn entries(&self) -> Box, Value<'_, D>)> + '_> { (*self).entries() } - fn is_embedded(&self) -> bool { (*self).is_embedded() } - fn embedded(&self) -> Cow<'_, D> { (*self).embedded() } - fn annotations(&self) -> Option> { (*self).annotations() } +impl Value { + pub fn copy(&self, f: &mut F) -> Result, Err> + where + F: FnMut(&V::Embedded) -> Result, Err> + { + W::copy(self, f) + } } -impl<'va, D: Domain> ValueImpl for PlainValue<'va, D> { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { self.as_ref().write(w, enc) } - fn value_clone(&self) -> PlainValue<'static, D> { self.as_ref().value_clone() } - fn value_class(&self) -> ValueClass { self.as_ref().value_class() } - fn as_boolean(&self) -> Option { self.as_ref().as_boolean() } - fn as_float(&self) -> Option { self.as_ref().as_float() } - fn as_double(&self) -> Option { self.as_ref().as_double() } - fn is_signed_integer(&self) -> bool { self.as_ref().is_signed_integer() } - fn as_signed_integer(&self) -> Option { self.as_ref().as_signed_integer() } - fn as_string(&self) -> Option> { self.as_ref().as_string() } - fn as_bytestring(&self) -> Option> { self.as_ref().as_bytestring() } - fn as_symbol(&self) -> Option> { self.as_ref().as_symbol() } - fn is_record(&self) -> bool { self.as_ref().is_record() } - fn label(&self) -> Value<'_, D> { self.as_ref().label() } - fn is_sequence(&self) -> bool { self.as_ref().is_sequence() } - fn len(&self) -> usize { self.as_ref().len() } - fn index(&self, i: usize) -> Value<'_, D> { self.as_ref().index(i) } - fn iter(&self) -> Box> + '_> { self.as_ref().iter() } - fn is_set(&self) -> bool { self.as_ref().is_set() } - fn has(&self, v: &dyn ValueImpl) -> bool { self.as_ref().has(v) } - fn is_dictionary(&self) -> bool { self.as_ref().is_dictionary() } - fn get(&self, k: &dyn ValueImpl) -> Option> { self.as_ref().get(k) } - fn entries(&self) -> Box, Value<'_, D>)> + '_> { self.as_ref().entries() } - fn is_embedded(&self) -> bool { self.as_ref().is_embedded() } - fn embedded(&self) -> Cow<'_, D> { self.as_ref().embedded() } - fn annotations(&self) -> Option> { self.as_ref().annotations() } -} - -impl<'a, D: Domain> Debug for dyn ValueImpl + 'a { +impl Debug for Value { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { TextWriter::fmt_value(f, &mut DefaultDomainCodec, self).map_err(|_| std::fmt::Error) } } -impl, D: Domain + FromStr> FromStr for PlainValue<'static, D> { +impl, D: Domain + FromStr, V: ValueImpl> + FromStr for Value +{ type Err = io::Error; fn from_str(s: &str) -> Result { @@ -283,7 +131,7 @@ impl, D: Domain + FromStr> FromStr for PlainValu } } -impl<'a, D: Domain> Hash for dyn ValueImpl + 'a { +impl Hash for Value { fn hash(&self, state: &mut H) { match self.value_class() { ValueClass::Atomic(a) => match a { @@ -314,12 +162,12 @@ impl<'a, D: Domain> Hash for dyn ValueImpl + 'a { } } } - ValueClass::Embedded => self.embedded().hash(state), + ValueClass::Embedded => self.as_embedded().unwrap().hash(state), } } } -impl<'a, D: Domain> PartialEq for dyn ValueImpl + 'a { +impl PartialEq for Value { fn eq(&self, other: &Self) -> bool { let cls = self.value_class(); if cls != other.value_class() { return false; } @@ -359,12 +207,12 @@ impl<'a, D: Domain> PartialEq for dyn ValueImpl + 'a { d1 == d2 } } - ValueClass::Embedded => self.embedded() == other.embedded(), + ValueClass::Embedded => self.as_embedded().unwrap() == other.as_embedded().unwrap(), } } } -impl<'a, D: Domain> Ord for dyn ValueImpl + 'a { +impl Ord for Value { fn cmp(&self, other: &Self) -> Ordering { let cls = self.value_class(); cls.cmp(&other.value_class()).then_with(|| match cls { @@ -400,14 +248,14 @@ impl<'a, D: Domain> Ord for dyn ValueImpl + 'a { d1.cmp(&d2) } }, - ValueClass::Embedded => self.embedded().cmp(&other.embedded()), + ValueClass::Embedded => self.as_embedded().unwrap().cmp(&other.as_embedded().unwrap()), }) } } -impl<'a, D: Domain> Eq for dyn ValueImpl + 'a {} +impl Eq for Value {} -impl<'a, D: Domain> PartialOrd for dyn ValueImpl + 'a { +impl PartialOrd for Value { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } @@ -418,24 +266,28 @@ pub enum Atom<'a> { Boolean(bool), Float(f32), Double(f64), - SignedInteger(SignedInteger), + SignedInteger(Cow<'a, SignedInteger>), String(Cow<'a, str>), ByteString(Cow<'a, [u8]>), Symbol(Cow<'a, str>), } impl<'a> Atom<'a> { - pub fn into_value<'b: 'a, D: Domain>(self) -> PlainValue<'b, D> { + fn write(&self, w: &mut dyn Writer) -> io::Result<()> { match self { - Atom::Boolean(b) => Box::new(b), - Atom::Float(f) => Box::new(f), - Atom::Double(d) => Box::new(d), - Atom::SignedInteger(i) => Box::new(i), - Atom::String(s) => Box::new(s.into_owned()), - Atom::ByteString(bs) => Box::new(Bytes(bs.into_owned())), - Atom::Symbol(s) => Box::new(Symbol(s.into_owned())), + Atom::Boolean(b) => w.write_bool(*b), + Atom::Float(f) => w.write_f32(*f), + Atom::Double(d) => w.write_f64(*d), + Atom::SignedInteger(i) => w.write_signed_integer(i), + Atom::String(s) => w.write_string(s), + Atom::ByteString(bs) => w.write_bytes(bs), + Atom::Symbol(s) => w.write_symbol(s), } } + + fn symbol>>(v: W) -> Self { + Atom::Symbol(v.into()) + } } impl<'r, 'a> From<&'r Atom<'a>> for AtomClass { @@ -452,56 +304,15 @@ impl<'r, 'a> From<&'r Atom<'a>> for AtomClass { } } -impl<'a, D: Domain> ValueImpl for Atom<'a> { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { - match self { - Atom::Boolean(b) => w.write_bool(*b), - Atom::Float(f) => w.write_f32(*f), - Atom::Double(d) => w.write_f64(*d), - Atom::SignedInteger(i) => w.write_signed_integer(i), - Atom::String(s) => w.write_string(s), - Atom::ByteString(bs) => w.write_bytes(bs), - Atom::Symbol(s) => w.write_symbol(s), - } - } - - fn value_clone(&self) -> PlainValue<'static, D> { - self.clone().into_value() - } - - fn value_class(&self) -> ValueClass { - ValueClass::Atomic(self.into()) - } - - fn as_boolean(&self) -> Option { - if let Atom::Boolean(b) = self { Some(*b) } else { None } - } - - fn as_float(&self) -> Option { - if let Atom::Float(f) = self { Some(*f) } else { None } - } - - fn as_double(&self) -> Option { - if let Atom::Double(d) = self { Some(*d) } else { None } - } - - fn is_signed_integer(&self) -> bool { matches!(self, Atom::SignedInteger(_)) } - fn as_signed_integer(&self) -> Option { - if let Atom::SignedInteger(i) = self { Some(i.clone()) } else { None } - } - - fn as_string(&self) -> Option> { - if let Atom::String(s) = self { Some(Cow::Borrowed(s)) } else { None } - } - - fn as_bytestring(&self) -> Option> { - if let Atom::ByteString(s) = self { Some(Cow::Borrowed(s)) } else { None } - } - - fn as_symbol(&self) -> Option> { - if let Atom::Symbol(s) = self { Some(Cow::Borrowed(s)) } else { None } - } -} +impl<'a> From for Atom<'a> { fn from(v: bool) -> Self { Atom::Boolean(v) } } +impl<'a> From for Atom<'a> { fn from(v: f32) -> Self { Atom::Float(v) } } +impl<'a> From for Atom<'a> { fn from(v: f64) -> Self { Atom::Double(v) } } +impl<'a> From<&'a SignedInteger> for Atom<'a> { fn from(v: &'a SignedInteger) -> Self { Atom::SignedInteger(Cow::Borrowed(v)) } } +impl<'a> From for Atom<'a> { fn from(v: SignedInteger) -> Self { Atom::SignedInteger(Cow::Owned(v)) } } +impl<'a> From<&'a str> for Atom<'a> { fn from(v: &'a str) -> Self { Atom::String(Cow::Borrowed(v)) } } +impl<'a> From for Atom<'a> { fn from(v: String) -> Self { Atom::String(Cow::Owned(v)) } } +impl<'a> From<&'a [u8]> for Atom<'a> { fn from(v: &'a [u8]) -> Self { Atom::ByteString(Cow::Borrowed(v)) } } +impl<'a> From> for Atom<'a> { fn from(v: Vec) -> Self { Atom::ByteString(Cow::Owned(v)) } } #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub enum NoValue {} @@ -519,99 +330,373 @@ impl FromStr for NoValue { } } -impl ValueImpl for NoValue { - fn write(&self, _w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { unreachable!() } - fn value_clone(&self) -> PlainValue<'static, D> { unreachable!() } +pub struct NoIterator { + nothing: NoValue, + phantom: PhantomData, +} + +impl Iterator for NoIterator { + type Item = A; + + fn next(&mut self) -> Option { + None + } +} + +impl ValueImpl for NoValue { + type Embedded = NoValue; + type Mapped<_E: Domain> = NoValue; + type Items<'a> = NoIterator<&'a Value>; + type Entries<'a> = NoIterator<(&'a Value, &'a Value)>; + + fn write(&self, _w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { unreachable!() } fn value_class(&self) -> ValueClass { unreachable!() } -} + fn as_boolean(&self) -> Option { unreachable!() } + fn as_float(&self) -> Option { unreachable!() } + fn as_double(&self) -> Option { unreachable!() } + fn as_signed_integer(&self) -> Option> { unreachable!() } + fn as_string(&self) -> Option> { unreachable!() } + fn as_bytestring(&self) -> Option> { unreachable!() } + fn as_symbol(&self) -> Option> { unreachable!() } + fn is_record(&self) -> bool { unreachable!() } + fn label(&self) -> Value { unreachable!() } + fn is_sequence(&self) -> bool { unreachable!() } + fn len(&self) -> usize { unreachable!() } + fn index(&self, _i: usize) -> Value { unreachable!() } + fn iter(&self) -> Self::Items<'_> { unreachable!() } + fn is_set(&self) -> bool { unreachable!() } + fn has>(&self, _v: &Value) -> bool { unreachable!() } + fn is_dictionary(&self) -> bool { unreachable!() } + fn get>(&self, _k: &Value) -> Option> { unreachable!() } + fn entries(&self) -> Self::Entries<'_> { unreachable!() } + fn as_embedded(&self) -> Option> { unreachable!() } + fn annotations(&self) -> Option> { unreachable!() } + fn peeled(&self) -> &Self { unreachable!() } -impl ValueImpl for bool { - fn write(&self, w: &mut dyn Writer, __enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_bool(*self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(*self) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Boolean) } - fn as_boolean(&self) -> Option { Some(*self) } -} + fn copy(w: &Value, f: &mut F) -> Result, Err> + where + F: FnMut(&E::Embedded) -> Result, Err> + { + panic!("Cannot copy into NoValue") + } -impl ValueImpl for u64 { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_u64(*self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(*self) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::SignedInteger) } - fn as_signed_integer(&self) -> Option { - Some((*self).into()) + fn map_embedded(&self, f: &mut F) -> Result>, Err> + where + F: FnMut(&Self::Embedded) -> Result + { + unreachable!() } } -impl ValueImpl for SignedInteger { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_signed_integer(self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(self.clone()) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::SignedInteger) } - fn as_signed_integer(&self) -> Option { - Some(self.clone()) +pub enum Shell<'a, V: ValueImpl> { + Atom(Atom<'a>), + Record(Record>), + Sequence(Vec>), + Set(Set>), + Dictionary(Map, Value>), + Embedded(V::Embedded), + Annotated(Annotations), +} + +impl Shell<'static, Arc>> { + pub fn record(label: ArcValue, fields: Vec>) -> ArcValue { + Value(Arc::new(ArcValueImpl(Shell::Record(Record::new(label, fields)), PhantomData))) } } -impl ValueImpl for f32 { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_f32(*self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(*self) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) } - fn as_float(&self) -> Option { Some(*self) } - fn as_double(&self) -> Option { Some(*self as f64) } -} +impl<'a, V: ValueImpl> ValueImpl for Shell<'a, V> { + type Embedded = V::Embedded; + type Mapped = Shell<'a, V::Mapped>; + type Items<'i> = std::slice::Iter<'i, Value> where Self: 'i; + type Entries<'i> = std::collections::btree_map::Iter<'i, Value, Value> where Self: 'i; -impl ValueImpl for f64 { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_f64(*self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(*self) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Float) } - fn as_float(&self) -> Option { Some(*self as f32) } - fn as_double(&self) -> Option { Some(*self) } -} + fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { + match self { + Shell::Atom(a) => a.write(w), + Shell::Record(_) => todo!(), + Shell::Sequence(items) => { + w.start_sequence()?; + let mut b = B::Type::default(); + for e in items { + b.shift(Some(B::Item::SequenceValue)); + w.boundary(&b)?; + e.write(w, enc)?; + } + b.shift(None); + w.boundary(&b)?; + w.end_sequence() + } + Shell::Set(items) => { + w.start_set()?; + let mut b = B::Type::default(); + for e in items.iter() { + b.shift(Some(B::Item::SetValue)); + w.boundary(&b)?; + e.write(w, enc)?; + } + b.shift(None); + w.boundary(&b)?; + w.end_set() + } + Shell::Dictionary(entries) => { + w.start_dictionary()?; + let mut b = B::Type::default(); + for (k, v) in entries.iter() { + b.shift(Some(B::Item::DictionaryKey)); + w.boundary(&b)?; + k.write(w, enc)?; + b.shift(Some(B::Item::DictionaryValue)); + w.boundary(&b)?; + v.write(w, enc)?; + } + b.shift(None); + w.boundary(&b)?; + w.end_dictionary() + } + Shell::Embedded(d) => { + w.start_embedded()?; + enc.encode_embedded(w, d)?; + w.end_embedded() + } + Shell::Annotated(b) => { + let (value, anns) = b.as_ref(); + w.start_annotations()?; + let mut b = B::Type::default(); + for ann in &anns { + b.shift(Some(B::Item::Annotation)); + w.boundary(&b)?; + ann.write(w, &mut IOValueDomainCodec)?; + } + b.shift(Some(B::Item::AnnotatedValue)); + w.boundary(&b)?; + value.write(w, enc)?; + b.shift(None); + w.boundary(&b)?; + w.end_annotations() + } + } + } -impl ValueImpl for str { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_string(self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(self.to_owned()) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::String) } - fn as_string(&self) -> Option> { Some(Cow::Borrowed(self)) } -} + fn value_class(&self) -> ValueClass { + match self { + Shell::Atom(a) => ValueClass::Atomic(a.into()), + Shell::Record(_) => ValueClass::Compound(CompoundClass::Record), + Shell::Sequence(_) => ValueClass::Compound(CompoundClass::Sequence), + Shell::Set(_) => ValueClass::Compound(CompoundClass::Set), + Shell::Dictionary(_) => ValueClass::Compound(CompoundClass::Dictionary), + Shell::Embedded(_) => ValueClass::Embedded, + Shell::Annotated(b) => b.0.0.value_class(), + } + } -impl ValueImpl for String { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_string(self) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(self.clone()) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::String) } - fn as_string(&self) -> Option> { Some(Cow::Borrowed(self)) } -} + fn copy(w: &Value, f: &mut F) -> Result, Err> + where + F: FnMut(&E::Embedded) -> Result, Err> + { + let r = match w.value_class() { + ValueClass::Atomic(a) => match a { + AtomClass::Boolean => Shell::Atom(Atom::Boolean(w.as_boolean().unwrap())), + AtomClass::Float => Shell::Atom(Atom::Float(w.as_float().unwrap())), + AtomClass::Double => Shell::Atom(Atom::Double(w.as_double().unwrap())), + AtomClass::SignedInteger => Shell::Atom(Atom::SignedInteger(w.as_signed_integer().unwrap())), + AtomClass::String => Shell::Atom(Atom::String(w.as_string().unwrap())), + AtomClass::ByteString => Shell::Atom(Atom::ByteString(w.as_bytestring().unwrap())), + AtomClass::Symbol => Shell::Atom(Atom::Symbol(w.as_symbol().unwrap())), + }, + ValueClass::Compound(c) => match c { + CompoundClass::Sequence => + Shell::Sequence(w.iter().map(|ww| ww.copy(f)).collect::, _>>()?), + CompoundClass::Set => + Shell::Set(w.iter().map(|ww| ww.copy(f)).collect::, _>>()?), + CompoundClass::Record => + Shell::Record(Record::new( + w.label().copy(f)?, + w.iter().map(|ww| ww.copy(f)).collect::, _>>()?)), + CompoundClass::Dictionary => + Shell::Dictionary(w.entries().map(|(k, ww)| Ok((k.copy(f)?, ww.copy(f)?))) + .collect::, _>>()?), + }, + ValueClass::Embedded => f(&w.as_embedded().unwrap())?.0, + }; + } -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[repr(transparent)] -pub struct Bytes + Debug = Vec>(T); + fn map_embedded(&self, f: &mut F) -> Result>, Err> + where + F: FnMut(&V::Embedded) -> Result + { + Self::copy(self, &mut |d| Ok(Self::Embedded(f(d)?))) + } -impl + Debug> Bytes { - pub fn new(t: T) -> Self { - Bytes(t) + fn as_boolean(&self) -> Option { + match self { + Shell::Atom(Atom::Boolean(b)) => Some(*b), + _ => None, + } + } + + fn as_float(&self) -> Option { + match self { + Shell::Atom(Atom::Float(f)) => Some(*f), + _ => None, + } + } + + fn as_double(&self) -> Option { + match self { + Shell::Atom(Atom::Double(d)) => Some(*d), + _ => None, + } + } + + fn as_signed_integer(&self) -> Option> { + match self { + Shell::Atom(Atom::SignedInteger(i)) => Some(Cow::Borrowed(i)), + _ => None, + } + } + + fn as_string(&self) -> Option> { + match self { + Shell::Atom(Atom::String(s)) => Some(Cow::Borrowed(s)), + _ => None, + } + } + + fn as_bytestring(&self) -> Option> { + match self { + Shell::Atom(Atom::ByteString(bs)) => Some(Cow::Borrowed(bs)), + _ => None, + } + } + + fn as_symbol(&self) -> Option> { + match self { + Shell::Atom(Atom::Symbol(s)) => Some(Cow::Borrowed(s)), + _ => None, + } + } + + fn is_record(&self) -> bool { + matches!(self, Shell::Record(_)) + } + + fn label(&self) -> Value { + match self { + Shell::Record(items) => items.0[0], + _ => panic!("Not a record"), + } + } + + fn is_sequence(&self) -> bool { + matches!(self, Shell::Sequence(_)) + } + + fn len(&self) -> usize { + match self { + Shell::Record(items) => items.0.len() - 1, + Shell::Sequence(items) => items.len(), + Shell::Set(items) => items.len(), + Shell::Dictionary(entries) => entries.len(), + _ => panic!("Not a compound value"), + } + } + + fn index(&self, i: usize) -> Value { + match self { + Shell::Record(items) => items.0[i - 1], + Shell::Sequence(items) => items[i], + _ => panic!("Not indexable"), + } + } + + fn iter(&self) -> Self::Items<'_> { + match self { + Shell::Record(items) => items.0[1..].iter(), + Shell::Sequence(items) => items.iter(), + Shell::Set(items) => todo!(), // TODO: don't use slice iter directly + _ => panic!("Not iterable"), + } + } + + fn is_set(&self) -> bool { + matches!(self, Shell::Set(_)) + } + + fn has>(&self, v: &Value) -> bool { + match self { + Shell::Set(items) => items.contains(v), + _ => false, + } + } + + fn is_dictionary(&self) -> bool { + matches!(self, Shell::Dictionary(_)) + } + + fn get>(&self, k: &Value) -> Option> { + match self { + Shell::Dictionary(entries) => entries.get(k), + _ => None, + } + } + + fn entries(&self) -> Self::Entries<'_> { + match self { + Shell::Dictionary(entries) => entries.iter(), + _ => panic!("Not a dictionary"), + } + } + + fn as_embedded(&self) -> Option> { + match self { + Shell::Embedded(d) => Some(Cow::Borrowed(d)), + _ => None, + } + } + + fn annotations(&self) -> Option> { + match self { + Shell::Annotated(b) => Some(Cow::Borrowed(&b.1)), + _ => None, + } + } + + fn peeled(&self) -> &Self { + match self { + Shell::Annotated(b) => Some(b.0), + _ => self, + } } } -impl + Debug, D: Domain> ValueImpl for Bytes { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_bytes(self.0.as_ref()) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(Bytes(self.0.as_ref().to_owned())) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::ByteString) } - fn as_bytestring(&self) -> Option> { Some(Cow::Borrowed(self.0.as_ref())) } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[repr(transparent)] -pub struct Symbol + Debug = String>(T); - -impl + Debug> Symbol { - pub fn new(t: T) -> Self { - Symbol(t) +impl From for Value { + fn from(v: V) -> Self { + Value(v) } } -impl + Debug, D: Domain> ValueImpl for Symbol { - fn write(&self, w: &mut dyn Writer, _enc: &mut dyn DomainEncode) -> io::Result<()> { w.write_symbol(self.0.as_ref()) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(Symbol(self.0.as_ref().to_owned())) } - fn value_class(&self) -> ValueClass { ValueClass::Atomic(AtomClass::Symbol) } - fn as_symbol(&self) -> Option> { Some(Cow::Borrowed(self.0.as_ref())) } +impl<'a, W: Into>, V: ValueImpl> From for Shell<'a, V> { + fn from(w: W) -> Self { + Shell::Atom(w.into()) + } +} + +impl<'a, V: ValueImpl> From>> for Shell<'a, V> { + fn from(vs: Vec>) -> Self { + Shell::Sequence(vs) + } +} + +impl<'a, V: ValueImpl> From>> for Shell<'a, V> { + fn from(vs: Set>) -> Self { + Shell::Set(vs) + } +} + +impl<'a, V: ValueImpl> From, Value>> for Shell<'a, V> { + fn from(vs: Map, Value>) -> Self { + Shell::Dictionary(vs) + } } #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] @@ -634,414 +719,116 @@ impl Record { } } -impl> ValueImpl for Record { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - w.start_record()?; - let mut b = B::start(B::Item::RecordLabel); - w.boundary(&b)?; - self.0[0].write(w, enc)?; - for e in &self.0[1..] { - b.shift(Some(B::Item::RecordField)); - w.boundary(&b)?; - e.write(w, enc)?; - } - b.shift(None); - w.boundary(&b)?; - w.end_record() - } +#[derive(Clone)] +pub struct Annotations(Box<(Value, Vec)>); - fn value_clone(&self) -> PlainValue<'static, D> { - Box::new(Record(self.0.iter().map(|v| v.value_clone()).collect())) - } - - fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Record) } - fn is_record(&self) -> bool { true } - fn label(&self) -> Value<'_, D> { Value::Borrowed(&self.0[0]) } - fn len(&self) -> usize { self.0.len() - 1 } - fn index(&self, i: usize) -> Value<'_, D> { Value::Borrowed(&self.0[i + 1]) } - fn iter(&self) -> Box> + '_> { - Box::new(self.0[1..].iter().map(value)) - } -} - -impl> ValueImpl for Vec { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - (&self[..]).write(w, enc) - } - - fn value_clone(&self) -> PlainValue<'static, D> { - (&self[..]).value_clone() - } - - fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) } - fn is_sequence(&self) -> bool { true } - fn len(&self) -> usize { self.len() } - fn index(&self, i: usize) -> Value<'_, D> { Value::Borrowed(&self[i]) } - fn iter(&self) -> Box> + '_> { - Box::new(self[..].iter().map(value)) - } -} - -impl> ValueImpl for [V] { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - w.start_sequence()?; - let mut b = B::Type::default(); - for e in self { - b.shift(Some(B::Item::SequenceValue)); - w.boundary(&b)?; - e.write(w, enc)?; - } - b.shift(None); - w.boundary(&b)?; - w.end_sequence() - } - - fn value_clone(&self) -> PlainValue<'static, D> { - Box::new(self.iter().map(|v| v.value_clone()).collect::>()) - } - - fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Sequence) } - fn is_sequence(&self) -> bool { true } - fn len(&self) -> usize { self.len() } - fn index(&self, i: usize) -> Value<'_, D> { Value::Borrowed(&self[i]) } - fn iter(&self) -> Box> + '_> { - Box::new(self[..].iter().map(value)) - } -} - -impl Borrow> + Ord + 'static> ValueImpl for Set { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - w.start_set()?; - let mut b = B::Type::default(); - for e in self { - b.shift(Some(B::Item::SetValue)); - w.boundary(&b)?; - Key::peel_ref(e.borrow()).write(w, enc)?; - } - b.shift(None); - w.boundary(&b)?; - w.end_set() - } - - fn value_clone(&self) -> PlainValue<'static, D> { - Box::new(self.iter().map(|v| Key::peel_ref(&v.borrow()).value_clone()).collect::>()) - } - - fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Set) } - fn is_set(&self) -> bool { true } - fn len(&self) -> usize { self.len() } - fn has(&self, v: &dyn ValueImpl) -> bool { self.contains(&Key::wrap_ref(v)) } - fn iter(&self) -> Box> + '_> { - Box::new(self.iter().map(|e| Value::Borrowed(Key::peel_ref(&e.borrow())))) - } -} - -// Many thanks to SkiFire13 and the other participants in -// https://users.rust-lang.org/t/is-the-lifetime-of-a-btreemap-get-result-attached-to-the-key-as-well-as-the-map/83568/7 -// for the idea of using TransparentWrapper here. -// -#[derive(PartialEq, Eq, PartialOrd, Ord)] -#[repr(transparent)] -pub struct Key<'a, D: Domain>(pub dyn ValueImpl + 'a); -unsafe impl<'a, D: Domain> TransparentWrapper + 'a> for Key<'a, D> {} - -impl<'a, 'b: 'a, D: Domain> Borrow> for PlainValue<'b, D> { - fn borrow(&self) -> &Key<'a, D> { - Key::wrap_ref(&**self) - } -} - -impl<'a, 'b: 'a, D: Domain> Borrow> for &'b (dyn ValueImpl + 'b) { - fn borrow(&self) -> &Key<'a, D> { - Key::wrap_ref(self) - } -} - -impl + 'static, K: for<'a> Borrow> + Ord + 'static> ValueImpl - for Map -{ - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - w.start_dictionary()?; - let mut b = B::Type::default(); - for (k, v) in self { - b.shift(Some(B::Item::DictionaryKey)); - w.boundary(&b)?; - Key::peel_ref(k.borrow()).write(w, enc)?; - b.shift(Some(B::Item::DictionaryValue)); - w.boundary(&b)?; - v.write(w, enc)?; - } - b.shift(None); - w.boundary(&b)?; - w.end_dictionary() - } - - fn value_clone(&self) -> PlainValue<'static, D> { - Box::new(ValueImpl::entries(self).map(|(k, v)| (k.value_clone(), v.value_clone())).collect::>()) - } - - fn value_class(&self) -> ValueClass { ValueClass::Compound(CompoundClass::Dictionary) } - fn is_dictionary(&self) -> bool { true } - fn len(&self) -> usize { self.len() } - fn has(&self, v: &dyn ValueImpl) -> bool { self.contains_key(&Key::wrap_ref(v)) } - fn get(&self, k: &dyn ValueImpl) -> Option> { - match Map::get(self, &Key::wrap_ref(k)) { - Some(v) => Some(Value::Borrowed(v)), - None => None, - } - } - fn entries(&self) -> Box, Value<'_, D>)> + '_> { - Box::new(self.iter().map( - |(k,v)| (Value::Borrowed(Key::peel_ref(&k.borrow())), value(v)))) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[repr(transparent)] -pub struct Embedded(D); - -impl Embedded { - pub fn new(d: D) -> Self { - Embedded(d) - } - - pub fn embedded_value(&self) -> &D { - &self.0 - } - - pub fn into_embedded_value(self) -> D { - self.0 - } -} - -impl ValueImpl for Embedded { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - w.start_embedded()?; - enc.encode_embedded(w, &self.0)?; - w.end_embedded() - } - - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(self.clone()) } - fn value_class(&self) -> ValueClass { ValueClass::Embedded } - fn is_embedded(&self) -> bool { true } - fn embedded(&self) -> Cow<'_, D> { Cow::Borrowed(&self.0) } -} - -#[derive(Debug)] -pub struct Annotations + 'static>(V, Vec, PhantomData); - -impl> Annotations { - pub fn new(value: V, anns: Vec) -> Self { - Annotations(value, anns, PhantomData) - } - - pub fn value(&self) -> &dyn ValueImpl { - &self.0 - } -} - -impl> ValueImpl for Annotations { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { - if !self.1.is_empty() { - w.start_annotations()?; - let mut b = B::Type::default(); - for ann in &self.1 { - b.shift(Some(B::Item::Annotation)); - w.boundary(&b)?; - ann.write(w, &mut IOValueDomainCodec)?; - } - b.shift(Some(B::Item::AnnotatedValue)); - w.boundary(&b)?; - self.0.write(w, enc)?; - b.shift(None); - w.boundary(&b)?; - w.end_annotations() - } else { - self.0.write(w, enc) - } - } - - fn value_clone(&self) -> PlainValue<'static, D> { - Box::new(Annotations(self.0.value_clone(), - self.1.iter().map(|v| v.value_clone().into()).collect(), - PhantomData)) - } - - fn value_class(&self) -> ValueClass { self.value().value_class() } - fn as_boolean(&self) -> Option { self.value().as_boolean() } - fn as_float(&self) -> Option { self.value().as_float() } - fn as_double(&self) -> Option { self.value().as_double() } - fn is_signed_integer(&self) -> bool { self.value().is_signed_integer() } - fn as_signed_integer(&self) -> Option { self.value().as_signed_integer() } - fn as_string(&self) -> Option> { self.value().as_string() } - fn as_bytestring(&self) -> Option> { self.value().as_bytestring() } - fn as_symbol(&self) -> Option> { self.value().as_symbol() } - fn is_record(&self) -> bool { self.value().is_record() } - fn label(&self) -> Value<'_, D> { self.value().label() } - fn is_sequence(&self) -> bool { self.value().is_sequence() } - fn len(&self) -> usize { self.value().len() } - fn index(&self, i: usize) -> Value<'_, D> { self.value().index(i) } - fn iter(&self) -> Box> + '_> { self.value().iter() } - fn is_set(&self) -> bool { self.value().is_set() } - fn has(&self, v: &dyn ValueImpl) -> bool { self.value().has(v) } - fn is_dictionary(&self) -> bool { self.value().is_dictionary() } - fn get(&self, k: &dyn ValueImpl) -> Option> { self.value().get(k) } - fn entries(&self) -> Box, Value<'_, D>)> + '_> { self.value().entries() } - fn is_embedded(&self) -> bool { self.value().is_embedded() } - fn embedded(&self) -> Cow<'_, D> { self.value().embedded() } - fn annotations(&self) -> Option> { Some(Cow::Borrowed(&self.1)) } -} - -impl> PartialEq for Annotations { - fn eq(&self, other: &Self) -> bool { - self.value().eq(&other.value()) - } -} - -impl> Eq for Annotations {} - -impl> Hash for Annotations { +impl Hash for Annotations { fn hash(&self, state: &mut H) { - self.value().hash(state); + self.0.as_ref().0.hash(state) } } -impl> PartialOrd for Annotations { +impl PartialEq for Annotations { + fn eq(&self, other: &Self) -> bool { + self.0.as_ref().0.eq(other.0.as_ref().0) + } +} + +impl Ord for Annotations { + fn cmp(&self, other: &Self) -> Ordering { + self.0.as_ref().0.cmp(other.0.as_ref().0) + } +} + +impl Eq for Annotations {} + +impl PartialOrd for Annotations { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } } -impl> Ord for Annotations { - fn cmp(&self, other: &Self) -> Ordering { - self.value().cmp(&other.value()) - } -} - -#[derive(Clone, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] -pub struct ArcValue(Arc>); +pub struct ArcValueImpl(Shell<'static, Arc>>, PhantomData); +pub type ArcValue = Value>>; #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] -pub struct IOValue(ArcValue); +pub struct IOValueImpl(ArcValueImpl); +pub type IOValue = Value>; -impl Debug for ArcValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - value(self).fmt(f) - } -} - -impl Debug for IOValue { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - value(self).fmt(f) - } -} - -impl PartialEq for ArcValue { - fn eq(&self, other: &Self) -> bool { - &self.0 == &other.0 - } -} - -impl, D: Domain + FromStr> FromStr for ArcValue { - type Err = io::Error; - - fn from_str(s: &str) -> Result { - Ok(arcvalue(crate::annotated_from_str(s, &mut DefaultDomainCodec)?.value_clone())) - } -} - -impl FromStr for IOValue { - type Err = io::Error; - - fn from_str(s: &str) -> Result { - crate::annotated_iovalue_from_str(s) - } -} - -impl From> for ArcValue { - fn from(b: PlainValue<'static, D>) -> Self { - ArcValue(Arc::from(b)) - } -} - -impl From> for IOValue { - fn from(b: PlainValue<'static, IOValue>) -> Self { - IOValue(b.into()) - } -} +unsafe impl bytemuck::TransparentWrapper> for IOValueImpl {} impl From> for IOValue { - fn from(b: ArcValue) -> Self { - IOValue(b) + fn from(v: ArcValue) -> Self { + IOValue::wrap_arc(v) } } -impl<'a> Borrow> for IOValue { - fn borrow(&self) -> &Key<'a, IOValue> { - Key::wrap_ref(&*self.0.0) +impl From for ArcValue { + fn from(v: IOValue) -> Self { + IOValue::peel_arc(v) } } -impl<'a, D: Domain> Borrow> for ArcValue { - fn borrow(&self) -> &Key<'a, D> { - Key::wrap_ref(&*self.0) - } +impl ValueImpl for ArcValueImpl { } -impl ValueImpl for ArcValue { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { self.0.write(w, enc) } - fn value_clone(&self) -> PlainValue<'static, D> { Box::new(self.clone()) } - fn value_class(&self) -> ValueClass { self.0.value_class() } - fn as_boolean(&self) -> Option { self.0.as_boolean() } - fn as_float(&self) -> Option { self.0.as_float() } - fn as_double(&self) -> Option { self.0.as_double() } - fn is_signed_integer(&self) -> bool { self.0.is_signed_integer() } - fn as_signed_integer(&self) -> Option { self.0.as_signed_integer() } - fn as_string(&self) -> Option> { self.0.as_string() } - fn as_bytestring(&self) -> Option> { self.0.as_bytestring() } - fn as_symbol(&self) -> Option> { self.0.as_symbol() } - fn is_record(&self) -> bool { self.0.is_record() } - fn label(&self) -> Value<'_, D> { self.0.label() } - fn is_sequence(&self) -> bool { self.0.is_sequence() } - fn len(&self) -> usize { self.0.len() } - fn index(&self, i: usize) -> Value<'_, D> { self.0.index(i) } - fn iter(&self) -> Box> + '_> { self.0.iter() } - fn is_set(&self) -> bool { self.0.is_set() } - fn has(&self, v: &dyn ValueImpl) -> bool { self.0.has(v) } - fn is_dictionary(&self) -> bool { self.0.is_dictionary() } - fn get(&self, k: &dyn ValueImpl) -> Option> { self.0.get(k) } - fn entries(&self) -> Box, Value<'_, D>)> + '_> { self.0.entries() } - fn is_embedded(&self) -> bool { self.0.is_embedded() } - fn embedded(&self) -> Cow<'_, D> { self.0.embedded() } - fn annotations(&self) -> Option> { self.0.annotations() } +impl ValueImpl for IOValueImpl { } -impl ValueImpl for IOValue { - fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode) -> io::Result<()> { self.0.write(w, enc) } - fn value_clone(&self) -> PlainValue<'static, IOValue> { Box::new(self.clone()) } - fn value_class(&self) -> ValueClass { self.0.value_class() } - fn as_boolean(&self) -> Option { self.0.as_boolean() } - fn as_float(&self) -> Option { self.0.as_float() } - fn as_double(&self) -> Option { self.0.as_double() } - fn is_signed_integer(&self) -> bool { self.0.is_signed_integer() } - fn as_signed_integer(&self) -> Option { self.0.as_signed_integer() } - fn as_string(&self) -> Option> { self.0.as_string() } - fn as_bytestring(&self) -> Option> { self.0.as_bytestring() } - fn as_symbol(&self) -> Option> { self.0.as_symbol() } - fn is_record(&self) -> bool { self.0.is_record() } - fn label(&self) -> Value<'_, IOValue> { self.0.label() } - fn is_sequence(&self) -> bool { self.0.is_sequence() } - fn len(&self) -> usize { self.0.len() } - fn index(&self, i: usize) -> Value<'_, IOValue> { self.0.index(i) } - fn iter(&self) -> Box> + '_> { self.0.iter() } - fn is_set(&self) -> bool { self.0.is_set() } - fn has(&self, v: &dyn ValueImpl) -> bool { self.0.has(v) } - fn is_dictionary(&self) -> bool { self.0.is_dictionary() } - fn get(&self, k: &dyn ValueImpl) -> Option> { self.0.get(k) } - fn entries(&self) -> Box, Value<'_, IOValue>)> + '_> { self.0.entries() } - fn is_embedded(&self) -> bool { self.0.is_embedded() } - fn embedded(&self) -> Cow<'_, IOValue> { self.0.embedded() } - fn annotations(&self) -> Option> { self.0.annotations() } +impl ValueImpl for Arc { } + +// impl Debug for ArcValue { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// value(self).fmt(f) +// } +// } + +// impl Debug for IOValue { +// fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +// value(self).fmt(f) +// } +// } + +// impl PartialEq for ArcValue { +// fn eq(&self, other: &Self) -> bool { +// &self.0 == &other.0 +// } +// } + +// impl, D: Domain + FromStr> FromStr for ArcValue { +// type Err = io::Error; + +// fn from_str(s: &str) -> Result { +// Ok(arcvalue(crate::annotated_from_str(s, &mut DefaultDomainCodec)?.value_clone())) +// } +// } + +// impl FromStr for IOValue { +// type Err = io::Error; + +// fn from_str(s: &str) -> Result { +// crate::annotated_iovalue_from_str(s) +// } +// } + +// impl From> for ArcValue { +// fn from(b: PlainValue<'static, D>) -> Self { +// ArcValue(Arc::from(b)) +// } +// } + +// impl From> for IOValue { +// fn from(b: PlainValue<'static, IOValue>) -> Self { +// IOValue(b.into()) +// } +// } + +// impl From> for IOValue { +// fn from(b: ArcValue) -> Self { +// IOValue(b) +// } +// } diff --git a/implementations/rust/preserves/src/signed_integer.rs b/implementations/rust/preserves/src/signed_integer.rs index b64fe13..1a459df 100644 --- a/implementations/rust/preserves/src/signed_integer.rs +++ b/implementations/rust/preserves/src/signed_integer.rs @@ -7,8 +7,17 @@ use std::convert::TryFrom; use std::convert::TryInto; use std::fmt; +#[derive(Debug)] pub struct OutOfRange(pub BigInt); +impl fmt::Display for OutOfRange { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "The value {:?} is out of range", &self.0) + } +} + +impl std::error::Error for OutOfRange {} + impl From for crate::error::Error { fn from(e: OutOfRange) -> Self { crate::error::Error::NumberOutOfRange(e.0) diff --git a/implementations/rust/preserves/src/text/writer.rs b/implementations/rust/preserves/src/text/writer.rs index fb559ab..d02e694 100644 --- a/implementations/rust/preserves/src/text/writer.rs +++ b/implementations/rust/preserves/src/text/writer.rs @@ -1,4 +1,3 @@ -use crate::Domain; use crate::DomainEncode; use crate::IOValue; use crate::IOValueDomainCodec; @@ -36,10 +35,10 @@ impl std::default::Default for CommaStyle { } impl TextWriter<&mut Vec> { - pub fn fmt_value>( + pub fn fmt_value>( f: &mut std::fmt::Formatter<'_>, enc: &mut Enc, - v: &dyn ValueImpl, + v: &V, ) -> io::Result<()> { let mut buf: Vec = Vec::new(); let mut w = TextWriter::new(&mut buf); @@ -49,9 +48,9 @@ impl TextWriter<&mut Vec> { |_| io::Error::new(io::ErrorKind::Other, "could not append to Formatter")) } - pub fn encode>( + pub fn encode>( enc: &mut Enc, - v: &dyn ValueImpl, + v: &V, ) -> io::Result { let mut buf: Vec = Vec::new(); v.write(&mut TextWriter::new(&mut buf), enc)?; diff --git a/implementations/rust/preserves/src/writer.rs b/implementations/rust/preserves/src/writer.rs index cafc347..f83ad67 100644 --- a/implementations/rust/preserves/src/writer.rs +++ b/implementations/rust/preserves/src/writer.rs @@ -3,7 +3,6 @@ use std::io; use crate::AtomClass; use crate::CompoundClass; -use crate::Domain; use crate::DomainEncode; use crate::IOValueDomainCodec; use crate::SignedInteger; @@ -70,10 +69,10 @@ pub trait Writer { fn specialized(&mut self) -> Option<(&str, &mut dyn io::Write)> { None } } -pub fn write_value>( +pub fn write_value( w: &mut dyn Writer, - v: V, - enc: &mut dyn DomainEncode, + v: &V, + enc: &mut dyn DomainEncode, ) -> io::Result<()> { let annotations = v.annotations(); let mut annotation_b = B::Type::default();