diff --git a/implementations/rust/oo/src/lib.rs b/implementations/rust/oo/src/lib.rs index 531c89e..71a30ff 100644 --- a/implementations/rust/oo/src/lib.rs +++ b/implementations/rust/oo/src/lib.rs @@ -21,6 +21,7 @@ pub use packed::from_bytes; pub use packed::iovalue_from_bytes; pub use reader::Reader; pub use repr::Annotations; +pub use repr::ArcValue; pub use repr::Atom; pub use repr::Bytes; pub use repr::Embedded; diff --git a/implementations/rust/oo/src/packed/mod.rs b/implementations/rust/oo/src/packed/mod.rs index d536c06..9539001 100644 --- a/implementations/rust/oo/src/packed/mod.rs +++ b/implementations/rust/oo/src/packed/mod.rs @@ -12,13 +12,13 @@ use crate::BytesBinarySource; use crate::Domain; use crate::DomainDecode; use crate::IOValue; +use crate::PlainValue; use crate::Reader; -use crate::Value; pub fn from_bytes<'de, D: Domain + 'static, Dec: DomainDecode>( bs: &'de [u8], decode_embedded: &mut Dec, -) -> io::Result>> { +) -> io::Result> { BytesBinarySource::new(bs).packed().next(false, decode_embedded) } @@ -29,7 +29,7 @@ pub fn iovalue_from_bytes(bs: &[u8]) -> io::Result { pub fn annotated_from_bytes<'de, D: Domain + 'static, Dec: DomainDecode>( bs: &'de [u8], decode_embedded: &mut Dec, -) -> io::Result>> { +) -> io::Result> { super::BytesBinarySource::new(bs).packed().next(true, decode_embedded) } diff --git a/implementations/rust/oo/src/repr.rs b/implementations/rust/oo/src/repr.rs index 0e8eda8..47b8b78 100644 --- a/implementations/rust/oo/src/repr.rs +++ b/implementations/rust/oo/src/repr.rs @@ -26,7 +26,6 @@ use crate::domain::{NoEmbeddedDomainCodec, DomainEncode, IOValueDomainCodec}; use super::float::{eq_f32, eq_f64, cmp_f32, cmp_f64}; pub type PlainValue<'a, D = IOValue> = Box + 'a>; -pub type ArcValue = Arc>; /// Atomic values from the specification. pub trait Value { @@ -79,8 +78,12 @@ pub fn owned + 'static>(v: V) -> PlainValue<'static, D> { Box::new(v) } +pub fn arcvalue + 'static>(v: V) -> ArcValue { + ArcValue(Arc::new(v)) +} + pub fn iovalue + 'static>(v: V) -> IOValue { - IOValue(Arc::new(v)) + IOValue(arcvalue(v)) } pub fn copy_via( @@ -189,7 +192,7 @@ impl<'a, Err: Into, D: Domain + FromStr + 'static> FromStr type Err = io::Error; fn from_str(s: &str) -> Result { - crate::from_str(s, &mut DefaultDomainCodec) + crate::annotated_from_str(s, &mut DefaultDomainCodec) } } @@ -691,7 +694,7 @@ impl<'e, D: Domain, E: for<'a> Borrow> + Ord + 'e> Value for Set(pub dyn Value + 'a); unsafe impl<'a, D: Domain> TransparentWrapper + 'a> for Key<'a, D> {} -impl<'a, 'b: 'a, D: Domain> Borrow> for Box + 'b> { +impl<'a, 'b: 'a, D: Domain> Borrow> for PlainValue<'b, D> { fn borrow(&self) -> &Key<'a, D> { Key::wrap_ref(&**self) } @@ -864,40 +867,105 @@ impl> Ord for Annotations { } #[derive(Clone, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] +pub struct ArcValue(Arc>); + +#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[repr(transparent)] pub struct IOValue(ArcValue); +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 FromStr for IOValue { - type Err = io::Error; - - fn from_str(s: &str) -> Result { - crate::iovalue_from_str(s) - } -} - -impl PartialEq for IOValue { +impl PartialEq for ArcValue { fn eq(&self, other: &Self) -> bool { &self.0 == &other.0 } } +impl, D: Domain + FromStr + 'static> FromStr for ArcValue { + type Err = io::Error; + + fn from_str(s: &str) -> Result { + Ok(arcvalue(crate::annotated_from_str(s, &mut DefaultDomainCodec)?)) + } +} + +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(Arc::from(b)) + IOValue(b.into()) + } +} + +impl From> for IOValue { + fn from(b: ArcValue) -> Self { + IOValue(b) } } impl<'a> Borrow> for IOValue { fn borrow(&self) -> &Key<'a, IOValue> { + Key::wrap_ref(&*self.0.0) + } +} + +impl<'a, D: Domain> Borrow> for ArcValue { + fn borrow(&self) -> &Key<'a, D> { Key::wrap_ref(&*self.0) } } +impl Value 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) -> &dyn Value { self.0.label() } + fn is_sequence(&self) -> bool { self.0.is_sequence() } + fn len(&self) -> usize { self.0.len() } + fn index(&self, i: usize) -> &dyn Value { 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 Value) -> bool { self.0.has(v) } + fn is_dictionary(&self) -> bool { self.0.is_dictionary() } + fn get<'value>(&'value self, k: &dyn Value) -> Option<&'value dyn Value> { self.0.get(k) } + fn entries(&self) -> Box, &dyn Value)> + '_> { self.0.entries() } + fn is_embedded(&self) -> bool { self.0.is_embedded() } + fn embedded(&self) -> Cow<'_, D> { self.0.embedded() } + fn annotations(&self) -> Option<&[IOValue]> { self.0.annotations() } +} + impl Value 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()) } diff --git a/implementations/rust/oo/src/text/mod.rs b/implementations/rust/oo/src/text/mod.rs index d4027ed..5da5862 100644 --- a/implementations/rust/oo/src/text/mod.rs +++ b/implementations/rust/oo/src/text/mod.rs @@ -11,13 +11,13 @@ use crate::BytesBinarySource; use crate::Domain; use crate::DomainDecode; use crate::IOValue; +use crate::PlainValue; use crate::Reader; -use crate::Value; pub fn from_str<'de, D: Domain + 'static, Dec: DomainDecode>( s: &'de str, decode_embedded: &mut Dec, -) -> io::Result>> { +) -> io::Result> { BytesBinarySource::new(s.as_bytes()).text().next(false, decode_embedded) } @@ -28,10 +28,51 @@ pub fn iovalue_from_str(s: &str) -> io::Result { pub fn annotated_from_str<'de, D: Domain + 'static, Dec: DomainDecode>( s: &'de str, decode_embedded: &mut Dec, -) -> io::Result>> { +) -> io::Result> { BytesBinarySource::new(s.as_bytes()).text().next(true, decode_embedded) } pub fn annotated_iovalue_from_str(s: &str) -> io::Result { BytesBinarySource::new(s.as_bytes()).text().next_iovalue(true) } + +#[cfg(test)] +mod formatting_tests { + use crate::IOValue; + use crate::test_domain::Dom; + use crate::ArcValue; + + #[test] fn format_debug_and_parse() { + let v = "[1, {z: 2, a: #!\"One\"}, 3]".parse::>().unwrap(); + assert_eq!(format!("{:?}", &v), "[1, {a: #!\"One\", z: 2}, 3]"); + } + + #[test] fn format_pretty_debug_and_parse() { + let v = "[1, {z: 2, a: #!\"One\"}, 3]".parse::>().unwrap(); + assert_eq!(format!("{:#?}", &v), concat!( + "[\n", + " 1,\n", + " {\n", + " a: #!\"One\",\n", + " z: 2\n", + " },\n", + " 3\n", + "]")); + } + + #[test] fn iovalue_parse() { + let v = "[1 @{a:b c:d} @\"foo\" #![2 3] 4]".parse::().unwrap(); + assert_eq!(format!("{:#?}", &v), concat!( + "[\n", + " 1,\n", + " @{\n", + " a: b,\n", + " c: d\n", + " } @\"foo\" #![\n", + " 2,\n", + " 3\n", + " ],\n", + " 4\n", + "]")); + } +}