diff --git a/implementations/rust/preserves/src/domain.rs b/implementations/rust/preserves/src/domain.rs index 8a96bda..507a751 100644 --- a/implementations/rust/preserves/src/domain.rs +++ b/implementations/rust/preserves/src/domain.rs @@ -1,17 +1,15 @@ use std::io; -use super::IOValue; use super::Reader; use super::Writer; -use super::ValueImpl; -pub trait Domain: std::fmt::Debug + Eq + std::hash::Hash + Ord + Clone + 'static { - type Decode: DomainDecode + Default; +pub trait Domain: std::fmt::Debug + Eq + std::hash::Hash + Ord + Clone { + type Decode: for<'de> DomainDecode<'de, Self> + Default; type Encode: DomainEncode + Default; } -pub trait DomainDecode { - fn decode_embedded<'de, R: Reader<'de> + ?Sized>( +pub trait DomainDecode<'de, D: Domain> { + fn decode_embedded + ?Sized>( &mut self, r: &mut R, read_annotations: bool, @@ -26,8 +24,8 @@ pub trait DomainEncode { ) -> io::Result<()>; } -impl<'a, D: Domain, T: DomainDecode> DomainDecode for &'a mut T { - fn decode_embedded<'de, R: Reader<'de> + ?Sized>( +impl<'a, 'de, D: Domain, T: DomainDecode<'de, D>> DomainDecode<'de, D> for &'a mut T { + fn decode_embedded + ?Sized>( &mut self, r: &mut R, read_annotations: bool, @@ -49,8 +47,8 @@ impl<'a, D: Domain, T: DomainEncode> DomainEncode for &'a mut T { #[derive(Default)] pub struct DefaultDomainCodec; -impl DomainDecode for DefaultDomainCodec { - fn decode_embedded<'de, R: Reader<'de> + ?Sized>( +impl<'de, D: Domain> DomainDecode<'de, D> for DefaultDomainCodec { + fn decode_embedded + ?Sized>( &mut self, r: &mut R, read_annotations: bool, @@ -72,8 +70,8 @@ impl DomainEncode for DefaultDomainCodec { #[derive(Default)] pub struct DebugDomainCodec; -impl, D: Domain + std::str::FromStr> DomainDecode for DebugDomainCodec { - fn decode_embedded<'de, R: Reader<'de> + ?Sized>( +impl<'de, Err: Into, D: Domain + std::str::FromStr> DomainDecode<'de, D> for DebugDomainCodec { + fn decode_embedded + ?Sized>( &mut self, r: &mut R, _read_annotations: bool, @@ -95,8 +93,8 @@ impl DomainEncode for DebugDomainCodec { #[derive(Default)] pub struct NoEmbeddedDomainCodec; -impl DomainDecode for NoEmbeddedDomainCodec { - fn decode_embedded<'de, R: Reader<'de> + ?Sized>( +impl<'de, D: Domain> DomainDecode<'de, D> for NoEmbeddedDomainCodec { + fn decode_embedded + ?Sized>( &mut self, _r: &mut R, _read_annotations: bool, @@ -114,26 +112,3 @@ impl DomainEncode for NoEmbeddedDomainCodec { Err(io::Error::new(io::ErrorKind::Unsupported, "Embedded values not supported here")) } } - -#[derive(Default)] -pub struct IOValueDomainCodec; - -impl DomainDecode for IOValueDomainCodec { - fn decode_embedded<'de, R: Reader<'de> + ?Sized>( - &mut self, - r: &mut R, - read_annotations: bool, - ) -> io::Result { - Ok(read_iovalue(r, read_annotations)?) - } -} - -impl DomainEncode for IOValueDomainCodec { - fn encode_embedded( - &mut self, - w: &mut dyn Writer, - d: &IOValue, - ) -> io::Result<()> { - d.write(w, self) - } -} diff --git a/implementations/rust/preserves/src/error.rs b/implementations/rust/preserves/src/error.rs index c869848..837dcfb 100644 --- a/implementations/rust/preserves/src/error.rs +++ b/implementations/rust/preserves/src/error.rs @@ -36,6 +36,12 @@ pub enum ExpectedKind { Annotation, } +#[derive(Debug)] +pub enum ReadError { + UnsupportedFormat, + Io(io::Error), +} + impl From for Error { fn from(e: ExpectedKind) -> Self { Error::Expected(e) @@ -48,6 +54,39 @@ impl From for Error { } } +impl From for Error { + fn from(e: ReadError) -> Self { + match e { + ReadError::UnsupportedFormat => Error::Message(format!("{}", e)), + ReadError::Io(i) => Error::Io(i), + } + } +} + +impl From for io::Error { + fn from(e: ReadError) -> Self { + match e { + ReadError::UnsupportedFormat => Error::from(e).into(), + ReadError::Io(i) => i, + } + } +} + +impl From for ReadError { + fn from(e: io::Error) -> Self { + ReadError::Io(e) + } +} + +impl std::fmt::Display for ReadError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ReadError::UnsupportedFormat => write!(f, "Unsupported Preserves format"), + ReadError::Io(i) => write!(f, "{}", i), + } + } +} + impl From for io::Error { fn from(e: Error) -> Self { match e { @@ -58,6 +97,8 @@ impl From for io::Error { } } +impl std::error::Error for ExpectedKind {} +impl std::error::Error for ReadError {} impl std::error::Error for Error {} impl std::fmt::Display for Error { @@ -66,6 +107,12 @@ impl std::fmt::Display for Error { } } +impl std::fmt::Display for ExpectedKind { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + pub fn io_eof() -> io::Error { io::Error::new(io::ErrorKind::UnexpectedEof, "EOF") } diff --git a/implementations/rust/preserves/src/iovalue.rs b/implementations/rust/preserves/src/iovalue.rs new file mode 100644 index 0000000..5ae8fcf --- /dev/null +++ b/implementations/rust/preserves/src/iovalue.rs @@ -0,0 +1,72 @@ +use std::borrow::Borrow; +use std::io; +use std::marker::PhantomData; + +use crate::DomainDecode; +use crate::Reader; +use crate::DomainEncode; +use crate::ValueImpl; +use crate::Writer; +use crate::ValueReader; + +pub struct IOValueDomainDecode(PhantomData); +pub struct IOValueDomainEncode(PhantomData); + +impl Default for IOValueDomainDecode { fn default() -> Self { Self(PhantomData) } } +impl Default for IOValueDomainEncode { fn default() -> Self { Self(PhantomData) } } + +impl<'de, V: ValueReader> DomainDecode<'de, as ValueImpl>::IOEmbedded> for IOValueDomainDecode { + fn decode_embedded + ?Sized>( + &mut self, + r: &mut R, + read_annotations: bool, + ) -> io::Result< as ValueImpl>::IOEmbedded> { + Ok(V::read_iovalue(r, read_annotations)?) + } +} + +impl DomainEncode for IOValueDomainEncode { + fn encode_embedded( + &mut self, + w: &mut dyn Writer, + d: &V::IOEmbedded, + ) -> io::Result<()> { + d.as_ref().borrow().write(w, self) + } +} + +pub struct IOValues<'de, V: ValueReader, R: Reader<'de>> { + pub reader: R, + pub read_annotations: bool, + phantom: PhantomData<&'de V>, +} + +impl<'de, V: ValueReader, R: Reader<'de>> IOValues<'de, V, R> { + pub fn new(reader: R) -> Self { + IOValues { + reader, + read_annotations: false, + phantom: PhantomData, + } + } + + pub fn read_annotations(mut self, read_annotations: bool) -> Self { + self.read_annotations = read_annotations; + self + } +} + +impl<'de, V: ValueReader, R: Reader<'de>> Iterator for IOValues<'de, V, R> { + type Item = io::Result< as ValueImpl>::IOEmbedded>; + + fn next(&mut self) -> Option { + match self.reader.peek_class() { + Err(e) => Some(Err(e)), + Ok(None) => None, + Ok(Some(_)) => match V::read_iovalue(&mut self.reader, self.read_annotations) { + Ok(v) => Some(Ok(v)), + Err(e) => Some(Err(e.into())), + } + } + } +} diff --git a/implementations/rust/preserves/src/lib.rs b/implementations/rust/preserves/src/lib.rs index 55371ea..de38f59 100644 --- a/implementations/rust/preserves/src/lib.rs +++ b/implementations/rust/preserves/src/lib.rs @@ -3,6 +3,7 @@ pub mod domain; pub mod error; pub mod float; pub mod hex; +pub mod iovalue; pub mod merge; pub mod packed; pub mod reader; @@ -10,26 +11,25 @@ pub mod repr; pub mod shell; pub mod signed_integer; pub mod source; -// pub mod text; +pub mod text; pub mod types; pub mod writer; pub use domain::*; pub use error::Error; pub use error::ExpectedKind; +pub use iovalue::IOValueDomainDecode; +pub use iovalue::IOValueDomainEncode; +pub use iovalue::IOValues; 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 reader::read; -pub use reader::read_iovalue; pub use repr::ValueImpl; +pub use repr::ValueReader; pub use repr::value_eq; pub use repr::value_cmp; pub use repr::value_hash; @@ -45,12 +45,10 @@ 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::from_str; pub use types::AtomClass; pub use types::CompoundClass; pub use types::ValueClass; diff --git a/implementations/rust/preserves/src/packed/mod.rs b/implementations/rust/preserves/src/packed/mod.rs index a34c97d..0c6a395 100644 --- a/implementations/rust/preserves/src/packed/mod.rs +++ b/implementations/rust/preserves/src/packed/mod.rs @@ -12,29 +12,20 @@ use crate::BinarySource; use crate::BytesBinarySource; use crate::Domain; use crate::DomainDecode; -use crate::IOValue; +use crate::Shell; use crate::ShellHandle; -use crate::read; -use crate::read_iovalue; +use crate::ValueReader; -pub fn from_bytes<'de, D: Domain, Dec: DomainDecode>( +pub fn from_bytes<'de, D: Domain, Dec: DomainDecode<'de, D>>( bs: &'de [u8], decode_embedded: &mut Dec, ) -> io::Result> { - read(&mut BytesBinarySource::new(bs).packed(), false, decode_embedded) + Ok(Shell::read(&mut BytesBinarySource::new(bs).packed(), false, decode_embedded)?) } -pub fn iovalue_from_bytes(bs: &[u8]) -> io::Result { - super::BytesBinarySource::new(bs).packed().next_iovalue(false) -} - -pub fn annotated_from_bytes<'de, D: Domain, Dec: DomainDecode>( +pub fn annotated_from_bytes<'de, D: Domain, Dec: DomainDecode<'de, D>>( bs: &'de [u8], decode_embedded: &mut Dec, ) -> io::Result> { - read(&mut super::BytesBinarySource::new(bs).packed(), true, decode_embedded) -} - -pub fn annotated_iovalue_from_bytes(bs: &[u8]) -> io::Result { - read_iovalue(&mut super::BytesBinarySource::new(bs).packed(), true) + Ok(Shell::read(&mut BytesBinarySource::new(bs).packed(), true, decode_embedded)?) } diff --git a/implementations/rust/preserves/src/packed/reader.rs b/implementations/rust/preserves/src/packed/reader.rs index 629a025..e768910 100644 --- a/implementations/rust/preserves/src/packed/reader.rs +++ b/implementations/rust/preserves/src/packed/reader.rs @@ -1,5 +1,8 @@ -use crate::{ValueClass, AtomClass, Atom}; -use crate::error::{self, ExpectedKind}; +use crate::ValueClass; +use crate::AtomClass; +use crate::Atom; +use crate::error::ExpectedKind; +use crate::error; use num_bigint::BigInt; use num_traits::cast::{FromPrimitive, ToPrimitive}; diff --git a/implementations/rust/preserves/src/packed/view.rs b/implementations/rust/preserves/src/packed/view.rs index 9f6c14a..bdf658b 100644 --- a/implementations/rust/preserves/src/packed/view.rs +++ b/implementations/rust/preserves/src/packed/view.rs @@ -1,5 +1,8 @@ +use std::borrow::Borrow; use std::borrow::Cow; use std::fmt::Debug; +use std::hash::Hash; +use std::hash::Hasher; use std::io; use std::marker::PhantomData; use std::ops::Range; @@ -11,7 +14,6 @@ use crate::BinarySource; use crate::BytesBinarySource; use crate::Domain; use crate::DomainDecode; -use crate::IOValue; use crate::NoEmbeddedDomainCodec; use crate::PackedWriter; use crate::SignedInteger; @@ -20,6 +22,7 @@ use crate::ValueImpl; use crate::error; use crate::error::io_eof; use crate::reader::NextToken; +use crate::value_eq; use super::constants::Tag; @@ -29,24 +32,28 @@ struct Index { } #[derive(Debug)] -struct IndexedRepr<'de, Packed: AsRef<[u8]> + 'de, D> { - packed: Packed, +struct IndexedRepr<'de, D> { + packed: Cow<'de, [u8]>, index: Index, phantom: PhantomData<&'de ()>, } -pub struct View<'de, Packed: AsRef<[u8]> + 'de, D: Domain> { - repr: Arc>, +pub struct View<'de, D: Domain> { + repr: Arc>, annotation_offset: usize, value_range: Range, } +#[repr(transparent)] +pub struct IOView<'de>(IOViewImpl<'de>); +pub type IOViewImpl<'de> = View<'de, IOView<'de>>; + struct IndexInProgress<'dec, D, Dec> { embedded: Vec<(Range, D)>, dec: &'dec mut Dec, } -struct Indexer<'de, 'dec, D: Domain, Dec: DomainDecode> { +struct Indexer<'de, 'dec, D: Domain, Dec: DomainDecode<'de, D>> { packed: &'de [u8], offset: usize, index: Option>, @@ -79,7 +86,7 @@ fn varint(packed: &[u8], mut i: usize) -> io::Result<(u64, usize)> { } } -impl<'de, 'dec, D: Domain, Dec: DomainDecode> Indexer<'de, 'dec, D, Dec> { +impl<'de, 'dec, D: Domain, Dec: DomainDecode<'de, D>> Indexer<'de, 'dec, D, Dec> { fn skip_annotations(&mut self) -> io::Result<()> { loop { if tag_at(&self.packed, self.offset)? == Tag::Annotation { @@ -160,10 +167,10 @@ impl<'de, 'dec, D: Domain, Dec: DomainDecode> Indexer<'de, 'dec, D, Dec> { } } -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> IndexedRepr<'de, Packed, D> { - fn trim(&self, range: Range) -> Arc, D>> { +impl<'de, D: Domain> IndexedRepr<'de, D> { + fn trim(&self, range: Range) -> Arc> { Arc::new(IndexedRepr { - packed: self.packed.as_ref()[range.clone()].to_vec().into_boxed_slice(), + packed: self.packed.as_ref()[range.clone()].to_vec().into(), index: Index { embedded: match self.index.embedded.as_ref() { Some(e) => { @@ -183,12 +190,12 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> IndexedRepr<'de, Packed, D> { } } -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> View<'de, Packed, D> { - pub fn new>(packed: Packed, dec: Option<&mut Dec>) -> io::Result { +impl<'de, D: Domain> View<'de, D> { + pub fn new>(packed: Cow<'de, [u8]>, dec: Option<&mut Dec>) -> io::Result { Self::new_offset(packed, dec, 0) } - pub fn trim(&self) -> View<'static, Box<[u8]>, D> { + pub fn trim(&self) -> View<'static, D> { View { repr: self.repr.trim(self.annotation_offset .. self.value_range.end), annotation_offset: 0, @@ -197,7 +204,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> View<'de, Packed, D> { } } - pub fn new_offset>(packed: Packed, dec: Option<&mut Dec>, offset: usize) -> io::Result { + pub fn new_offset>(packed: Cow<'de, [u8]>, dec: Option<&mut Dec>, offset: usize) -> io::Result { let mut indexer = Indexer { packed: packed.as_ref(), offset, @@ -224,7 +231,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> View<'de, Packed, D> { }) } - fn inner_new(repr: &Arc>, offset: usize) -> io::Result { + fn inner_new(repr: &Arc>, offset: usize) -> io::Result { let mut indexer: Indexer = Indexer { packed: repr.packed.as_ref(), offset, @@ -292,7 +299,12 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> View<'de, Packed, D> { } } -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Clone for View<'de, Packed, D> { +impl<'de, D: Domain> Domain for View<'de, D> { + type Decode = NoEmbeddedDomainCodec; + type Encode = NoEmbeddedDomainCodec; +} + +impl<'de, D: Domain> Clone for View<'de, D> { fn clone(&self) -> Self { View { repr: self.repr.clone(), @@ -302,12 +314,13 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Clone for View<'de, Packed, D> { } } -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl for View<'de, Packed, D> { +impl<'de, D: Domain> ValueImpl for View<'de, D> { type Handle = Self; type Embedded = D; - type Mapped = View<'de, Packed, E>; - type Items<'a> = ViewIterator> where Self: 'a; - type Entries<'a> = DictionaryAdapter> where Self: 'a; + type Mapped = View<'de, E>; + type Items<'a> = ViewIterator> where Self: 'a; + type Entries<'a> = DictionaryAdapter> where Self: 'a; + type IOEmbedded = IOView<'de>; fn wrap(self) -> Self::Handle { self @@ -442,7 +455,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl for View<'de, Packed, } fn has>(&self, v: &E::Handle) -> bool { - self.iter().find(|e| v == &**e).is_some() + self.iter().find(|e| value_eq(v.borrow(), e)).is_some() } fn is_dictionary(&self) -> bool { @@ -451,7 +464,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl for View<'de, Packed, fn get>(&self, k: &K::Handle) -> Option { for (kk, vv) in self.entries() { - if &*kk == k { return Some(vv); } + if value_eq(k.borrow(), &kk) { return Some(vv); } } None } @@ -479,17 +492,17 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl for View<'de, Packed, } } - fn annotations(&self) -> Option> { + fn annotations(&self) -> Option as ValueImpl>::Handle]>> { if self.value_range.start == self.annotation_offset { None } else { let repr = Arc::new(IndexedRepr { - packed: self.repr.packed.as_ref(), - index: Index:: { embedded: None }, + packed: self.repr.packed.as_ref().into(), + index: Index:: { embedded: None }, phantom: PhantomData, }); - let anns: Vec = AnnotationAdapter(ViewIterator::inner_new(&repr, self.annotation_offset)) - .collect(); + let anns: Vec = + AnnotationAdapter(ViewIterator::inner_new(&repr, self.annotation_offset)).collect(); Some(Cow::Owned(anns)) } } @@ -515,17 +528,78 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl for View<'de, Packed, } } -crate::impl_value_methods!({'de, Packed: AsRef<[u8]> + 'de, D: Domain}, View<'de, Packed, D>); +crate::impl_value_methods!({'de, D: Domain}, View<'de, D>); -pub struct ViewStream<'de, 'dec, D: Domain, Dec: DomainDecode = ::Decode> { - buf: &'de [u8], +impl<'de> Clone for IOView<'de> { + fn clone(&self) -> Self { + Self(self.0.clone()) + } +} + +impl<'de> Debug for IOView<'de> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} + +impl<'de> Ord for IOView<'de> { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.0.cmp(&other.0) + } +} + +impl<'de> Hash for IOView<'de> { + fn hash(&self, state: &mut H) { + self.0.hash(state); + } +} + +impl<'de> PartialOrd for IOView<'de> { + fn partial_cmp(&self, other: &Self) -> Option { + self.0.partial_cmp(&other.0) + } +} + +impl<'de> PartialEq for IOView<'de> { + fn eq(&self, other: &Self) -> bool { + self.0 == other.0 + } +} + +impl<'de> Eq for IOView<'de> {} + +impl<'de> Domain for IOView<'de> { + type Decode = NoEmbeddedDomainCodec; + type Encode = NoEmbeddedDomainCodec; +} + +impl<'de> From> for IOView<'de> { + fn from(v: IOViewImpl<'de>) -> Self { + IOView(v) + } +} + +impl<'de> Into> for IOView<'de> { + fn into(self) -> IOViewImpl<'de> { + self.0 + } +} + +impl<'de> AsRef> for IOView<'de> { + fn as_ref(&self) -> &IOViewImpl<'de> { + &self.0 + } +} + +pub struct ViewStream<'de, 'dec, D: Domain, Dec: DomainDecode<'de, D> = ::Decode> { + buf: Cow<'de, [u8]>, dec: Option<&'dec mut Dec>, offset: usize, phantom: PhantomData<&'de D>, } -impl<'de, 'dec, D: Domain, Dec: DomainDecode> ViewStream<'de, 'dec, D, Dec> { - pub fn new(buf: &'de [u8], dec: Option<&'dec mut Dec>) -> Self { +impl<'de, 'dec, D: Domain, Dec: DomainDecode<'de, D>> ViewStream<'de, 'dec, D, Dec> { + pub fn new(buf: Cow<'de, [u8]>, dec: Option<&'dec mut Dec>) -> Self { ViewStream { buf, dec, @@ -535,8 +609,8 @@ impl<'de, 'dec, D: Domain, Dec: DomainDecode> ViewStream<'de, 'dec, D, Dec> { } } -impl<'de, 'dec, D: Domain, Dec: DomainDecode> Iterator for ViewStream<'de, 'dec, D, Dec> { - type Item = io::Result>; +impl<'de, 'dec, D: Domain, Dec: DomainDecode<'de, D>> Iterator for ViewStream<'de, 'dec, D, Dec> { + type Item = io::Result>; fn next(&mut self) -> Option { if self.offset >= self.buf.len() { @@ -558,14 +632,14 @@ pub struct ViewIterator { offset: usize, } -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ViewIterator> { - pub fn inner_new(repr: &Arc>, offset: usize) -> Self { +impl<'de, D: Domain> ViewIterator> { + pub fn inner_new(repr: &Arc>, offset: usize) -> Self { ViewIterator { repr: Arc::clone(repr), offset } } } -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for ViewIterator> { - type Item = View<'de, Packed, D>; +impl<'de, D: Domain> Iterator for ViewIterator> { + type Item = View<'de, D>; fn next(&mut self) -> Option { if let Ok(Tag::End) = tag_at(self.repr.packed.as_ref(), self.offset) { @@ -580,8 +654,8 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for ViewIterator(pub ViewIterator); -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for DictionaryAdapter> { - type Item = (View<'de, Packed, D>, View<'de, Packed, D>); +impl<'de, D: Domain> Iterator for DictionaryAdapter> { + type Item = (View<'de, D>, View<'de, D>); fn next(&mut self) -> Option { let k = self.0.next()?; @@ -592,8 +666,8 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for DictionaryAdapter(pub ViewIterator); -impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for AnnotationAdapter> { - type Item = View<'de, Packed, D>; +impl<'de> Iterator for AnnotationAdapter>> { + type Item = IOViewImpl<'de>; fn next(&mut self) -> Option { if let Ok(Tag::Annotation) = tag_at(self.0.repr.packed.as_ref(), self.0.offset) { diff --git a/implementations/rust/preserves/src/packed/writer.rs b/implementations/rust/preserves/src/packed/writer.rs index c4ebe1a..74c70b4 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, DomainEncode, IOValue, IOValueDomainCodec, Writer}; +use crate::{boundary as B, ValueImpl, DomainEncode, Writer}; struct Buffers { base: W, @@ -44,11 +44,6 @@ impl PackedWriter<&mut Vec> { v.write(&mut PackedWriter::new(&mut buf), enc)?; Ok(buf) } - - #[inline(always)] - pub fn encode_iovalue(v: &IOValue) -> io::Result> { - Self::encode(&mut IOValueDomainCodec, v) - } } pub fn varint(w: &mut W, mut v: u64) -> io::Result { diff --git a/implementations/rust/preserves/src/reader.rs b/implementations/rust/preserves/src/reader.rs index 350ec33..1ad28af 100644 --- a/implementations/rust/preserves/src/reader.rs +++ b/implementations/rust/preserves/src/reader.rs @@ -1,28 +1,16 @@ use std::borrow::Cow; use std::convert::TryFrom; use std::io; -use std::marker::PhantomData; +use crate::Atom; use crate::BinarySource; use crate::CompoundClass; -use crate::Shell; -use crate::ShellHandle; use crate::SignedInteger; use crate::ValueClass; -use crate::ValueImpl; use crate::boundary as B; -use crate::domain::Domain; -use crate::domain::DomainDecode; -use crate::domain::IOValueDomainCodec; use crate::error::Error; use crate::error::ExpectedKind; use crate::error::io_eof; -use crate::repr::Annotations; -use crate::repr::Atom; -use crate::repr::IOValue; -use crate::repr::Map; -use crate::repr::Record; -use crate::repr::Set; pub type ReaderResult = std::result::Result; @@ -178,126 +166,3 @@ pub trait Reader<'de> { fn specialized(&mut self) -> Option<(&str, &mut dyn BinarySource<'de>)> { None } } - -pub fn gather_annotations<'de, R: Reader<'de> + ?Sized>( - r: &mut R, -) -> io::Result, ValueClass)>> { - let mut anns = Vec::new(); - loop { - match r.peek_class()? { - None => return Ok(None), - Some(NextToken::Value(v)) => return Ok(Some((anns, v))), - Some(NextToken::Annotation) => { - r.open_annotation()?; - anns.push(read_iovalue(r, true)?); - r.close_annotation()?; - } - } - } -} - -pub fn read<'produced, 'de, R: Reader<'de> + ?Sized, D: Domain, Dec: DomainDecode>( - r: &mut R, - read_annotations: bool, - dec: &mut Dec, -) -> io::Result> { - let (anns, v) = match read_annotations { - true => gather_annotations(r)?.ok_or_else(io_eof)?, - false => (Vec::new(), r.skip_annotations()?.ok_or_else(io_eof)?), - }; - let value = match v { - ValueClass::Atomic(_) => - Shell::Atom(r.next_atom()?), - ValueClass::Embedded => { - r.open_embedded()?; - let v = dec.decode_embedded(r, read_annotations)?; - r.close_embedded()?; - Shell::Embedded(v) - } - ValueClass::Compound(CompoundClass::Record) => { - let mut vs = Vec::new(); - r.open_record()?; - let mut b = B::start(B::Item::RecordLabel); - r.boundary(&b)?; - vs.push(read(r, read_annotations, dec)?); - while !r.close_compound(&mut b, &B::Item::RecordField)? { - vs.push(read(r, read_annotations, dec)?); - } - Shell::Record(Record::_from_vec(vs)) - } - ValueClass::Compound(CompoundClass::Sequence) => { - let mut vs = Vec::new(); - r.open_sequence()?; - let mut b = B::Type::default(); - while !r.close_compound(&mut b, &B::Item::SequenceValue)? { - vs.push(read(r, read_annotations, dec)?); - } - Shell::Sequence(vs) - } - ValueClass::Compound(CompoundClass::Set) => { - let mut s = Set::new(); - r.open_set()?; - let mut b = B::Type::default(); - while !r.close_compound(&mut b, &B::Item::SetValue)? { - s.insert(read(r, read_annotations, dec)?); - } - Shell::Set(s) - } - ValueClass::Compound(CompoundClass::Dictionary) => { - let mut d = Map::new(); - r.open_dictionary()?; - let mut b = B::Type::default(); - while !r.close_compound(&mut b, &B::Item::DictionaryKey)? { - let k = read(r, read_annotations, dec)?; - b.shift(Some(B::Item::DictionaryValue)); - r.boundary(&b)?; - d.insert(k, read(r, read_annotations, dec)?); - } - Shell::Dictionary(d) - } - }; - if anns.is_empty() { - Ok(value.wrap()) - } else { - Ok(Shell::Annotated(Annotations::new(value.wrap(), anns)).wrap()) - } -} - -pub fn read_iovalue<'de, R: Reader<'de> + ?Sized>( - r: &mut R, - read_annotations: bool, -) -> io::Result { - Ok(read(r, read_annotations, &mut IOValueDomainCodec)?.into()) -} - -pub struct IOValues<'de, R: Reader<'de>> { - pub reader: R, - pub read_annotations: bool, - phantom: PhantomData<&'de ()>, -} - -impl<'de, R: Reader<'de>> IOValues<'de, R> { - pub fn new(reader: R) -> Self { - IOValues { - reader, - read_annotations: false, - phantom: PhantomData, - } - } - - pub fn read_annotations(mut self, read_annotations: bool) -> Self { - self.read_annotations = read_annotations; - self - } -} - -impl<'de, R: Reader<'de>> std::iter::Iterator for IOValues<'de, R> { - type Item = io::Result; - fn next(&mut self) -> Option { - match self.reader.peek_class() { - Err(e) => Some(Err(e)), - Ok(None) => None, - Ok(Some(_)) => Some(read_iovalue(&mut self.reader, self.read_annotations)), - } - } -} diff --git a/implementations/rust/preserves/src/repr.rs b/implementations/rust/preserves/src/repr.rs index 50c38e5..d91a05f 100644 --- a/implementations/rust/preserves/src/repr.rs +++ b/implementations/rust/preserves/src/repr.rs @@ -7,6 +7,10 @@ use std::hash::Hash; use std::hash::Hasher; use std::io; +use crate::DomainDecode; +use crate::Reader; +use crate::error::ReadError; +use crate::reader::NextToken; use crate::signed_integer::OutOfRange; use crate::AtomClass; use crate::CompoundClass; @@ -19,6 +23,46 @@ use crate::write_value; use super::float::{eq_f32, eq_f64, cmp_f32, cmp_f64}; +pub trait ValueReader { + type Impl<'de>: ValueImpl; + + fn read_impl<'de, R: Reader<'de> + ?Sized, Dec: DomainDecode< as ValueImpl>::Embedded>>( + r: &mut R, + read_annotations: bool, + dec: &mut Dec, + ) -> Result, ReadError>; + + fn read<'de, R: Reader<'de> + ?Sized, Dec: DomainDecode< as ValueImpl>::Embedded>>( + r: &mut R, + read_annotations: bool, + dec: &mut Dec, + ) -> Result< as ValueImpl>::Handle, ReadError> { + Ok(Self::read_impl(r, read_annotations, dec)?.wrap()) + } + + fn read_iovalue<'de, R: Reader<'de> + ?Sized>( + r: &mut R, + read_annotations: bool, + ) -> Result< as ValueImpl>::IOEmbedded, ReadError>; + + fn gather_annotations<'de, R: Reader<'de> + ?Sized>( + r: &mut R, + ) -> io::Result as ValueImpl>::Mapped< as ValueImpl>::IOEmbedded> as ValueImpl>::Handle>, ValueClass)>> { + let mut anns = Vec::new(); + loop { + match r.peek_class()? { + None => return Ok(None), + Some(NextToken::Value(v)) => return Ok(Some((anns, v))), + Some(NextToken::Annotation) => { + r.open_annotation()?; + anns.push(Self::read_iovalue(r, true)?.into()); + r.close_annotation()?; + } + } + } + } +} + /// Atomic values from the specification. pub trait ValueImpl: Sized { type Handle: Borrow + Clone + From + Hash + Eq + Ord + PartialEq + PartialOrd; @@ -26,7 +70,11 @@ pub trait ValueImpl: Sized { type Mapped: ValueImpl; type Items<'a>: Iterator + 'a where Self: 'a; type Entries<'a>: Iterator + 'a where Self: 'a; - type IOValueImpl: ValueImpl::Handle>; + + type IOEmbedded: From< as ValueImpl>::Handle> + + Into< as ValueImpl>::Handle> + + AsRef< as ValueImpl>::Handle> + + Domain; fn wrap(self) -> Self::Handle; @@ -75,7 +123,7 @@ pub trait ValueImpl: Sized { fn as_embedded(&self) -> Option>; // INVARIANT: return Some() *only* when the contained collection is nonempty - fn annotations(&self) -> Option::Handle]>>; + fn annotations(&self) -> Option as ValueImpl>::Handle]>>; fn peeled(v: &Self::Handle) -> Self::Handle; @@ -219,13 +267,13 @@ pub fn value_cmp>(v: &V, w: & || iters_cmp::(&v.iter(), &w.iter())), CompoundClass::Sequence => iters_cmp::(&v.iter(), &w.iter()), CompoundClass::Set => { - let s1 = v.iter().collect::>(); - let s2 = w.iter().collect::>(); + let s1 = v.iter().collect::>(); + let s2 = w.iter().collect::>(); todo!() // s1.cmp(&s2) } CompoundClass::Dictionary => { - let d1 = v.entries().collect::>(); - let d2 = w.entries().collect::>(); + let d1 = v.entries().collect::>(); + let d2 = w.entries().collect::>(); todo!() // d1.cmp(&d2) } }, diff --git a/implementations/rust/preserves/src/shell.rs b/implementations/rust/preserves/src/shell.rs index f368c85..bac806c 100644 --- a/implementations/rust/preserves/src/shell.rs +++ b/implementations/rust/preserves/src/shell.rs @@ -13,15 +13,21 @@ use bytemuck::TransparentWrapper; use crate::AtomClass; use crate::CompoundClass; use crate::Domain; +use crate::DomainDecode; use crate::DomainEncode; use crate::ExpectedKind; -use crate::IOValueDomainCodec; +use crate::IOValueDomainDecode; +use crate::IOValueDomainEncode; +use crate::Reader; use crate::SignedInteger; use crate::ValueClass; use crate::ValueImpl; use crate::Writer; use crate::boundary as B; +use crate::error::ReadError; +use crate::error::io_eof; use crate::impl_value_methods; +use crate::repr::ValueReader; pub use std::collections::BTreeSet as Set; pub use std::collections::BTreeMap as Map; @@ -38,6 +44,18 @@ pub enum Atom<'a> { } impl<'a> Atom<'a> { + pub fn into_owned(self) -> Atom<'static> { + match self { + Atom::Boolean(b) => Atom::Boolean(b), + Atom::Float(f) => Atom::Float(f), + Atom::Double(d) => Atom::Double(d), + Atom::SignedInteger(i) => Atom::SignedInteger(i.to_owned()), + Atom::String(s) => Atom::String(s.to_owned()), + Atom::ByteString(bs) => Atom::ByteString(bs.to_owned()), + Atom::Symbol(s) => Atom::Symbol(s.to_owned()), + } + } + pub fn write(&self, w: &mut dyn Writer) -> io::Result<()> { match self { Atom::Boolean(b) => w.write_bool(*b), @@ -158,13 +176,35 @@ impl<'a, D: Domain> Shell<'a, D> { } } +impl ValueReader for Shell<'_, D> { + type Impl<'de> = Shell<'de, D>; + + fn read_impl<'de, R: Reader<'de> + ?Sized, Dec: DomainDecode<'de, as ValueImpl>::Embedded>>( + r: &mut R, + read_annotations: bool, + dec: &mut Dec, + ) -> Result, ReadError> { + Ok(read(r, read_annotations, dec)?) + } + + fn read_iovalue<'de, R: Reader<'de> + ?Sized>( + r: &mut R, + read_annotations: bool, + ) -> Result< as ValueImpl>::IOEmbedded, ReadError> { + Ok(Shell::<'de, IOValue>::read_impl( + r, + read_annotations, + &mut IOValueDomainDecode::>::default())?.into()) + } +} + impl<'a, D: Domain> ValueImpl for Shell<'a, D> { type Handle = ShellHandle<'a, D>; type Embedded = D; type Mapped = Shell<'a, E>; type Items<'i> = std::slice::Iter<'i, Self::Handle> where Self: 'i; type Entries<'i> = std::collections::btree_map::Iter<'i, Self::Handle, Self::Handle> where Self: 'i; - type IOValueImpl = IOValue; + type IOEmbedded = IOValue<'a>; fn wrap(self) -> Self::Handle { Self::Handle::new(self) @@ -225,7 +265,7 @@ impl<'a, D: Domain> ValueImpl for Shell<'a, D> { for ann in anns { b.shift(Some(B::Item::Annotation)); w.boundary(&b)?; - ann.value().write(w, &mut IOValueDomainCodec)?; + ann.write(w, &mut IOValueDomainEncode::::default())?; } b.shift(Some(B::Item::AnnotatedValue)); w.boundary(&b)?; @@ -284,7 +324,7 @@ impl<'a, D: Domain> ValueImpl for Shell<'a, D> { if let Some(anns) = w.annotations() { Ok(Shell::Annotated(Annotations(Box::new(( r, - anns.iter().map(copy_iovalue::).collect() + anns.iter().map(copy_iovalue::).map(|a| a.into()).collect() )))).wrap()) } else { Ok(r) @@ -426,7 +466,7 @@ impl<'a, D: Domain> ValueImpl for Shell<'a, D> { } } - fn annotations(&self) -> Option::Handle]>> { + fn annotations(&self) -> Option as ValueImpl>::Handle]>> { match self { Shell::Annotated(b) => Some(Cow::Borrowed(&b.0.as_ref().1)), _ => None, @@ -494,10 +534,10 @@ impl Record { } #[derive(Clone)] -pub struct Annotations(Box<(V::Handle, Vec<::Handle>)>); +pub struct Annotations(Box<(V::Handle, Vec< as ValueImpl>::Handle>)>); impl Annotations { - pub fn new(v: V::Handle, anns: Vec<::Handle>) -> Self { + pub fn new(v: V::Handle, anns: Vec< as ValueImpl>::Handle>) -> Self { Self(Box::new((v, anns))) } } @@ -528,47 +568,54 @@ impl PartialOrd for Annotations { } } -pub fn copy_iovalue::Handle>>(v: &V::Handle) -> IOValue { - IOValue::copy::(v, &mut |a| Result::<_, ()>::Ok(copy_iovalue::(a))).unwrap() +pub fn copy_iovalue(v: & as ValueImpl>::Handle) -> IOValue { + Shell::copy::, _, _>(v, &mut |a| Result::<_, ()>::Ok( + copy_iovalue::(a.as_ref()).into())).unwrap().into() } -pub type IOValueImpl = Shell<'static, IOValue>; +pub type IOValueImpl<'a> = Shell<'a, IOValue<'a>>; #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[repr(transparent)] -pub struct IOValue(ShellHandle<'static, IOValue>); -unsafe impl TransparentWrapper> for IOValue {} +pub struct IOValue<'a>(ShellHandle<'a, IOValue<'a>>); +unsafe impl<'a> TransparentWrapper>> for IOValue<'a> {} -impl Domain for IOValue { - type Decode = IOValueDomainCodec; - type Encode = IOValueDomainCodec; +impl Domain for IOValue<'_> { + type Decode = IOValueDomainDecode; + type Encode = IOValueDomainEncode; } -impl Debug for IOValue { +impl<'a> Debug for IOValue<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { IOValue::peel_ref(self).fmt(f) } } -impl IOValue { - pub fn value(&self) -> &IOValueImpl { +impl<'a> IOValue<'a> { + pub fn value(&self) -> &IOValueImpl<'a> { self.0.as_ref() } } -impl> From for IOValue { +impl<'a, T: Into>> From for IOValue<'a> { fn from(t: T) -> Self { IOValue(t.into().wrap()) } } -impl Borrow for IOValue { - fn borrow(&self) -> &IOValueImpl { +impl<'a> Borrow> for IOValue<'a> { + fn borrow(&self) -> &IOValueImpl<'a> { self.0.as_ref() } } -impl FromStr for IOValue { +impl<'a> AsRef>>> for IOValue<'a> { + fn as_ref(&self) -> &Arc>> { + &self.0 + } +} + +impl<'a> FromStr for IOValue<'a> { type Err = io::Error; fn from_str(s: &str) -> Result { @@ -576,37 +623,56 @@ impl FromStr for IOValue { } } -impl From<::Handle> for IOValue { - fn from(h: ::Handle) -> Self { +impl<'a> From< as ValueImpl>::Handle> for IOValue<'a> { + fn from(h: as ValueImpl>::Handle) -> Self { TransparentWrapper::wrap(h) } } -impl<'a> From<&'a ::Handle> for &'a IOValue { - fn from(h: &'a ::Handle) -> Self { +impl<'r, 'a> From<&'r as ValueImpl>::Handle> for &'r IOValue<'a> { + fn from(h: &'r as ValueImpl>::Handle) -> Self { TransparentWrapper::wrap_ref(h) } } -impl From for ::Handle { - fn from(i: IOValue) -> Self { +impl<'a> From> for as ValueImpl>::Handle { + fn from(i: IOValue<'a>) -> Self { IOValue::peel(i) } } -impl<'a> From<&'a IOValue> for &'a ::Handle { - fn from(i: &'a IOValue) -> Self { +impl<'r, 'a> From<&'r IOValue<'a>> for &'r as ValueImpl>::Handle { + fn from(i: &'r IOValue<'a>) -> Self { IOValue::peel_ref(i) } } -impl ValueImpl for IOValue { - type Handle = IOValue; - type Embedded = IOValue; - type Mapped = Shell<'static, E>; +impl<'a> ValueReader for IOValue<'a> { + type Impl<'i> = IOValue<'i>; + + fn read_impl<'de, R: Reader<'de> + ?Sized, Dec: DomainDecode<'de, as ValueImpl>::Embedded>>( + r: &mut R, + read_annotations: bool, + dec: &mut Dec, + ) -> Result, ReadError> { + Ok(read(r, read_annotations, dec)?.into()) + } + + fn read_iovalue<'de, R: Reader<'de> + ?Sized>( + r: &mut R, + read_annotations: bool, + ) -> Result< as ValueImpl>::IOEmbedded, ReadError> { + Self::read(r, read_annotations, &mut IOValueDomainDecode::::default()) + } +} + +impl<'a> ValueImpl for IOValue<'a> { + type Handle = Self; + type Embedded = Self; + type Mapped = Shell<'a, E>; type Items<'i> = std::slice::Iter<'i, Self::Handle> where Self: 'i; type Entries<'i> = std::collections::btree_map::Iter<'i, Self::Handle, Self::Handle> where Self: 'i; - type IOValueImpl = IOValue; + type IOEmbedded = Self; fn wrap(self) -> Self::Handle { self @@ -692,7 +758,7 @@ impl ValueImpl for IOValue { self.value().as_embedded() } - fn annotations(&self) -> Option> { + fn annotations(&self) -> Option as ValueImpl>::Handle]>> { self.value().annotations() } @@ -712,3 +778,70 @@ impl ValueImpl for IOValue { IOValueImpl::map_embedded(v.into(), f) } } + +pub fn read<'de, R: Reader<'de> + ?Sized, D: Domain, Dec: DomainDecode<'de, D>>( + r: &mut R, + read_annotations: bool, + dec: &mut Dec, +) -> io::Result> { + let (anns, v) = match read_annotations { + true => IOValue::gather_annotations(r)?.ok_or_else(io_eof)?, + false => (Vec::new(), r.skip_annotations()?.ok_or_else(io_eof)?), + }; + let value = match v { + ValueClass::Atomic(_) => + Shell::Atom(r.next_atom()?), + ValueClass::Embedded => { + r.open_embedded()?; + let v = dec.decode_embedded(r, read_annotations)?; + r.close_embedded()?; + Shell::Embedded(v) + } + ValueClass::Compound(CompoundClass::Record) => { + let mut vs = Vec::new(); + r.open_record()?; + let mut b = B::start(B::Item::RecordLabel); + r.boundary(&b)?; + vs.push(read(r, read_annotations, dec)?.wrap()); + while !r.close_compound(&mut b, &B::Item::RecordField)? { + vs.push(read(r, read_annotations, dec)?.wrap()); + } + Shell::Record(Record::_from_vec(vs)) + } + ValueClass::Compound(CompoundClass::Sequence) => { + let mut vs = Vec::new(); + r.open_sequence()?; + let mut b = B::Type::default(); + while !r.close_compound(&mut b, &B::Item::SequenceValue)? { + vs.push(read(r, read_annotations, dec)?.wrap()); + } + Shell::Sequence(vs) + } + ValueClass::Compound(CompoundClass::Set) => { + let mut s = Set::new(); + r.open_set()?; + let mut b = B::Type::default(); + while !r.close_compound(&mut b, &B::Item::SetValue)? { + s.insert(read(r, read_annotations, dec)?.wrap()); + } + Shell::Set(s) + } + ValueClass::Compound(CompoundClass::Dictionary) => { + let mut d = Map::new(); + r.open_dictionary()?; + let mut b = B::Type::default(); + while !r.close_compound(&mut b, &B::Item::DictionaryKey)? { + let k = read(r, read_annotations, dec)?.wrap(); + b.shift(Some(B::Item::DictionaryValue)); + r.boundary(&b)?; + d.insert(k, read(r, read_annotations, dec)?.wrap()); + } + Shell::Dictionary(d) + } + }; + if anns.is_empty() { + Ok(value) + } else { + Ok(Shell::Annotated(Annotations::new(value.wrap(), anns))) + } +} diff --git a/implementations/rust/preserves/src/text/mod.rs b/implementations/rust/preserves/src/text/mod.rs index 73aa688..411efe1 100644 --- a/implementations/rust/preserves/src/text/mod.rs +++ b/implementations/rust/preserves/src/text/mod.rs @@ -10,30 +10,22 @@ use crate::BinarySource; use crate::BytesBinarySource; use crate::Domain; use crate::DomainDecode; -use crate::IOValue; -use crate::PlainValue; -use crate::Reader; +use crate::Shell; +use crate::ShellHandle; +use crate::ValueReader; -pub fn from_str<'de, D: Domain, Dec: DomainDecode>( +pub fn from_str<'de, D: Domain, Dec: DomainDecode<'de, D>>( s: &'de str, decode_embedded: &mut Dec, -) -> io::Result> { - BytesBinarySource::new(s.as_bytes()).text().next(false, decode_embedded) +) -> io::Result> { + Ok(Shell::read(&mut BytesBinarySource::new(s.as_bytes()).text(), false, decode_embedded)?) } -pub fn iovalue_from_str(s: &str) -> io::Result { - BytesBinarySource::new(s.as_bytes()).text().next_iovalue(false) -} - -pub fn annotated_from_str<'de, D: Domain, Dec: DomainDecode>( +pub fn annotated_from_str<'de, D: Domain, Dec: DomainDecode<'de, D>>( s: &'de str, decode_embedded: &mut Dec, -) -> 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) +) -> io::Result> { + Ok(Shell::read(&mut BytesBinarySource::new(s.as_bytes()).text(), true, decode_embedded)?) } #[cfg(test)] diff --git a/implementations/rust/preserves/src/text/reader.rs b/implementations/rust/preserves/src/text/reader.rs index f382672..636fa3d 100644 --- a/implementations/rust/preserves/src/text/reader.rs +++ b/implementations/rust/preserves/src/text/reader.rs @@ -266,9 +266,9 @@ impl<'de, S: BinarySource<'de>> TextReader<'de, S> return match NUMBER_RE.captures(&s) { None => Ok(Atom::Symbol(s.into())), Some(m) => match m.get(2) { - None => Ok(Atom::SignedInteger(s.parse::().map_err( + None => Ok(Atom::SignedInteger(Cow::Owned(s.parse::().map_err( |_| self.syntax_error(&format!( - "Invalid signed-integer number: {:?}", s)))?.into())), + "Invalid signed-integer number: {:?}", s)))?.into()))), Some(_) => { if let Some(maybe_f) = m.get(7) { let s = m[1].to_owned() + &m[3]; diff --git a/implementations/rust/preserves/src/text/writer.rs b/implementations/rust/preserves/src/text/writer.rs index d02e694..ee06f59 100644 --- a/implementations/rust/preserves/src/text/writer.rs +++ b/implementations/rust/preserves/src/text/writer.rs @@ -1,6 +1,4 @@ use crate::DomainEncode; -use crate::IOValue; -use crate::IOValueDomainCodec; use crate::ValueImpl; use crate::Writer; use crate::hex::HexFormatter; @@ -56,10 +54,6 @@ impl TextWriter<&mut Vec> { v.write(&mut TextWriter::new(&mut buf), enc)?; Ok(String::from_utf8(buf).expect("valid UTF-8 from TextWriter")) } - - pub fn encode_iovalue(v: &IOValue) -> io::Result { - Self::encode(&mut IOValueDomainCodec, v) - } } impl TextWriter { diff --git a/implementations/rust/preserves/src/writer.rs b/implementations/rust/preserves/src/writer.rs index 0dff913..7b9502a 100644 --- a/implementations/rust/preserves/src/writer.rs +++ b/implementations/rust/preserves/src/writer.rs @@ -5,7 +5,7 @@ use std::io; use crate::AtomClass; use crate::CompoundClass; use crate::DomainEncode; -use crate::IOValueDomainCodec; +use crate::IOValueDomainEncode; use crate::SignedInteger; use crate::ValueClass; use crate::boundary as B; @@ -86,7 +86,7 @@ pub fn write_value( for ann in &anns[..] { annotation_b.shift(Some(B::Item::Annotation)); w.boundary(&annotation_b)?; - ann.borrow().write(w, &mut IOValueDomainCodec)?; + ann.borrow().write(w, &mut IOValueDomainEncode::::default())?; } annotation_b.shift(Some(B::Item::AnnotatedValue)); w.boundary(&annotation_b)?;