More WIP; Handles

This commit is contained in:
Tony Garnock-Jones 2022-11-18 15:21:33 +01:00
parent eeb50fcf65
commit 4070c5252d
10 changed files with 1159 additions and 996 deletions

View File

@ -118,18 +118,13 @@ impl<D: Domain> DomainEncode<D> for NoEmbeddedDomainCodec {
#[derive(Default)]
pub struct IOValueDomainCodec;
impl Domain for IOValue {
type Decode = IOValueDomainCodec;
type Encode = IOValueDomainCodec;
}
impl DomainDecode<IOValue> for IOValueDomainCodec {
fn decode_embedded<'de, R: Reader<'de> + ?Sized>(
&mut self,
r: &mut R,
read_annotations: bool,
) -> io::Result<IOValue> {
Ok(r.next_iovalue(read_annotations)?)
Ok(read_iovalue(r, read_annotations)?)
}
}

View File

@ -36,6 +36,12 @@ pub enum ExpectedKind {
Annotation,
}
impl From<ExpectedKind> for Error {
fn from(e: ExpectedKind) -> Self {
Error::Expected(e)
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Self {
Error::Io(e)

View File

@ -4,9 +4,10 @@ pub mod error;
pub mod float;
pub mod hex;
pub mod merge;
// pub mod packed;
pub mod packed;
pub mod reader;
pub mod repr;
pub mod shell;
pub mod signed_integer;
pub mod source;
// pub mod text;
@ -18,24 +19,28 @@ 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 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::IOValue;
pub use repr::Map;
pub use repr::NoValue;
pub use repr::Record;
pub use repr::Set;
pub use repr::Value;
pub use reader::read;
pub use reader::read_iovalue;
pub use repr::ValueImpl;
pub use repr::value_eq;
pub use repr::value_cmp;
pub use repr::value_hash;
pub use shell::Annotations;
pub use shell::Atom;
pub use shell::IOValue;
pub use shell::Map;
pub use shell::Record;
pub use shell::Set;
pub use shell::Shell;
pub use shell::ShellHandle;
pub use signed_integer::SignedInteger;
pub use source::BinarySource;
pub use source::BytesBinarySource;
@ -136,8 +141,8 @@ mod test_domain {
r: &mut R,
_read_annotations: bool,
) -> io::Result<Dom> {
let v = r.next_iovalue(false)?;
if v.as_bytestring().is_some() {
let v = read_iovalue(r, false)?;
if v.value().as_bytestring().is_some() {
Ok(Dom::One)
} else {
Ok(Dom::Two)
@ -152,32 +157,34 @@ mod test_domain {
d: &Dom,
) -> io::Result<()> {
match d {
Dom::One => Bytes::new(vec![255, 255, 255, 255]).write(w, self),
Dom::Two => Symbol::new(&format!("Dom::{:?}", d)).write(w, self),
Dom::One => Shell::from(vec![255, 255, 255, 255]).write(w, self),
Dom::Two => Shell::symbol(&format!("Dom::{:?}", d)).write(w, self),
}
}
}
fn dom_as_preserves(v: &Dom) -> io::Result<PlainValue<'static, IOValue>> {
fn dom_as_preserves(v: &Dom) -> io::Result<IOValue> {
Ok(match v {
Dom::One => owned(Bytes::new(vec![255, 255, 255, 255])),
Dom::Two => owned(Symbol::new(format!("Dom::{:?}", v))),
Dom::One => IOValue::from(vec![255, 255, 255, 255]),
Dom::Two => IOValueImpl::symbol(format!("Dom::{:?}", v)).into(),
})
}
#[test] fn test_one() {
let v = owned(vec![owned(1),
owned(Embedded::new(Dom::One)),
owned(2)]);
assert_eq!(PackedWriter::encode_iovalue(&iovalue(copy_via(&v, &mut dom_as_preserves).unwrap())).unwrap(),
let v = Shell::<Dom>::from(
vec![SignedInteger::from(1).into(),
Shell::embedded(Dom::One),
SignedInteger::from(2).into()]).wrap();
assert_eq!(PackedWriter::encode_iovalue(&IOValue::copy::<Shell::<Dom>, _, _>(&v, &mut dom_as_preserves).unwrap()).unwrap(),
[0xb5, 0x91, 0xb2, 0x04, 255, 255, 255, 255, 0x92, 0x84]);
}
#[test] fn test_two() {
let v = owned(vec![owned(1),
owned(Embedded::new(Dom::Two)),
owned(2)]);
assert_eq!(PackedWriter::encode_iovalue(&iovalue(copy_via(&v, &mut dom_as_preserves).unwrap())).unwrap(),
let v = Shell::<Dom>::from(
vec![SignedInteger::from(1).into(),
Shell::embedded(Dom::Two),
SignedInteger::from(2).into()]).wrap();
assert_eq!(PackedWriter::encode_iovalue(&IOValue::copy::<Shell::<Dom>, _, _>(&v, &mut dom_as_preserves).unwrap()).unwrap(),
[0xb5, 0x91, 0xb3, 0x08, 68, 111, 109, 58, 58, 84, 119, 111, 0x92, 0x84]);
}
}

View File

@ -1,6 +1,6 @@
pub mod constants;
pub mod reader;
// pub mod view;
pub mod view;
pub mod writer;
pub use reader::PackedReader;
@ -13,14 +13,15 @@ use crate::BytesBinarySource;
use crate::Domain;
use crate::DomainDecode;
use crate::IOValue;
use crate::PlainValue;
use crate::Reader;
use crate::ShellHandle;
use crate::read;
use crate::read_iovalue;
pub fn from_bytes<'de, D: Domain, Dec: DomainDecode<D>>(
bs: &'de [u8],
decode_embedded: &mut Dec,
) -> io::Result<PlainValue<'de, D>> {
BytesBinarySource::new(bs).packed().next(false, decode_embedded)
) -> io::Result<ShellHandle<'de, D>> {
read(&mut BytesBinarySource::new(bs).packed(), false, decode_embedded)
}
pub fn iovalue_from_bytes(bs: &[u8]) -> io::Result<IOValue> {
@ -30,10 +31,10 @@ pub fn iovalue_from_bytes(bs: &[u8]) -> io::Result<IOValue> {
pub fn annotated_from_bytes<'de, D: Domain, Dec: DomainDecode<D>>(
bs: &'de [u8],
decode_embedded: &mut Dec,
) -> io::Result<PlainValue<'de, D>> {
super::BytesBinarySource::new(bs).packed().next(true, decode_embedded)
) -> io::Result<ShellHandle<'de, D>> {
read(&mut super::BytesBinarySource::new(bs).packed(), true, decode_embedded)
}
pub fn annotated_iovalue_from_bytes(bs: &[u8]) -> io::Result<IOValue> {
super::BytesBinarySource::new(bs).packed().next_iovalue(true)
read_iovalue(&mut super::BytesBinarySource::new(bs).packed(), true)
}

View File

@ -300,11 +300,12 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
self.readbytes_into(&mut bs)?;
Ok(Atom::Double(f64::from_bits(u64::from_be_bytes(bs))))
}
Tag::SmallInteger(v) => Ok(Atom::SignedInteger(v.into())),
Tag::MediumInteger(count) => Ok(Atom::SignedInteger(self.read_signed_integer(count.into())?)),
Tag::SmallInteger(v) => Ok(Atom::SignedInteger(Cow::Owned(v.into()))),
Tag::MediumInteger(count) => Ok(Atom::SignedInteger(Cow::Owned(
self.read_signed_integer(count.into())?))),
Tag::SignedInteger => {
let count = self.varint()?;
Ok(Atom::SignedInteger(self.read_signed_integer(count)?))
Ok(Atom::SignedInteger(Cow::Owned(self.read_signed_integer(count)?)))
}
Tag::String => {
let count = self.varint()?;
@ -383,21 +384,21 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
}
}
fn next_signedinteger(&mut self) -> ReaderResult<SignedInteger> {
fn next_signedinteger(&mut self) -> ReaderResult<Cow<'de, SignedInteger>> {
let tag = self.peek_next_nonannotation_tag()?;
match tag {
Tag::SmallInteger(v) => {
self.skip()?;
Ok(SignedInteger::from(v as i32))
Ok(Cow::Owned(SignedInteger::from(v as i32)))
}
Tag::MediumInteger(count) => {
self.skip()?;
Ok(self.read_signed_integer(count.into())?)
Ok(Cow::Owned(self.read_signed_integer(count.into())?))
}
Tag::SignedInteger => {
self.skip()?;
let count = self.varint()?;
Ok(self.read_signed_integer(count)?)
Ok(Cow::Owned(self.read_signed_integer(count)?))
}
_ => Err(error::Error::Expected(ExpectedKind::SignedInteger))
}

View File

@ -14,33 +14,27 @@ use crate::DomainDecode;
use crate::IOValue;
use crate::NoEmbeddedDomainCodec;
use crate::PackedWriter;
use crate::PlainValue;
use crate::SignedInteger;
use crate::Value;
use crate::ValueClass;
use crate::ValueImpl;
use crate::error;
use crate::error::io_eof;
use crate::iovalue;
use crate::owned;
use crate::shell;
use crate::reader::NextToken;
use super::constants::Tag;
#[derive(Debug, Clone)]
#[derive(Debug)]
struct Index<D> {
embedded: Option<Box<[(Range<usize>, D)]>>,
}
#[derive(Debug, Clone)]
#[derive(Debug)]
struct IndexedRepr<'de, Packed: AsRef<[u8]> + 'de, D> {
packed: Packed,
index: Index<D>,
phantom: PhantomData<&'de ()>,
}
#[derive(Debug, Clone)]
pub struct View<'de, Packed: AsRef<[u8]> + 'de, D: Domain> {
repr: Arc<IndexedRepr<'de, Packed, D>>,
annotation_offset: usize,
@ -194,6 +188,15 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> View<'de, Packed, D> {
Self::new_offset(packed, dec, 0)
}
pub fn trim(&self) -> View<'static, Box<[u8]>, D> {
View {
repr: self.repr.trim(self.annotation_offset .. self.value_range.end),
annotation_offset: 0,
value_range: (self.value_range.start - self.annotation_offset
.. self.value_range.end - self.annotation_offset),
}
}
pub fn new_offset<Dec: DomainDecode<D>>(packed: Packed, dec: Option<&mut Dec>, offset: usize) -> io::Result<Self> {
let mut indexer = Indexer {
packed: packed.as_ref(),
@ -289,7 +292,27 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> View<'de, Packed, D> {
}
}
impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packed, D> {
impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Clone for View<'de, Packed, D> {
fn clone(&self) -> Self {
View {
repr: self.repr.clone(),
annotation_offset: self.annotation_offset,
value_range: self.value_range.clone()
}
}
}
impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl for View<'de, Packed, D> {
type Handle = Self;
type Embedded = D;
type Mapped<E: Domain> = View<'de, Packed, E>;
type Items<'a> = ViewIterator<IndexedRepr<'de, Packed, D>> where Self: 'a;
type Entries<'a> = DictionaryAdapter<IndexedRepr<'de, Packed, D>> where Self: 'a;
fn wrap(self) -> Self::Handle {
self
}
fn write(&self, w: &mut dyn crate::Writer, enc: &mut dyn crate::DomainEncode<D>) -> io::Result<()> {
match w.specialized() {
Some(("packed", mut w)) => {
@ -310,15 +333,6 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
}
}
fn value_clone(&self) -> PlainValue<'static, D> {
owned(View {
repr: self.repr.trim(self.annotation_offset .. self.value_range.end),
annotation_offset: 0,
value_range: (self.value_range.start - self.annotation_offset
.. self.value_range.end - self.annotation_offset),
})
}
fn value_class(&self) -> ValueClass {
match self.tag().into() {
Some(NextToken::Annotation) | None => unreachable!(),
@ -348,22 +362,13 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
}
}
fn is_signed_integer(&self) -> bool {
fn as_signed_integer(&self) -> Option<Cow<'_, SignedInteger>> {
match self.tag() {
Tag::SmallInteger(_) => true,
Tag::MediumInteger(_) => true,
Tag::SignedInteger => true,
_ => false,
}
}
fn as_signed_integer(&self) -> Option<SignedInteger> {
match self.tag() {
Tag::SmallInteger(v) => Some(v.into()),
Tag::MediumInteger(n) => Some(self.signed_integer(self.value_range.start + 1, n as usize)),
Tag::SmallInteger(v) => Some(Cow::Owned(v.into())),
Tag::MediumInteger(n) => Some(Cow::Owned(self.signed_integer(self.value_range.start + 1, n as usize))),
Tag::SignedInteger => {
let (n, i) = self.varint();
Some(self.signed_integer(i, n as usize))
Some(Cow::Owned(self.signed_integer(i, n as usize)))
}
_ => None,
}
@ -400,9 +405,9 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
self.tag() == Tag::Record
}
fn label(&self) -> Value<'_, D> {
fn label(&self) -> Self::Handle {
if !self.is_record() { panic!("Not a record") }
shell(View::inner_new(&self.repr, self.value_range.start + 1).unwrap())
View::inner_new(&self.repr, self.value_range.start + 1).unwrap()
}
fn is_sequence(&self) -> bool {
@ -417,12 +422,12 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
}
}
fn index(&self, i: usize) -> Value<'_, D> {
fn index(&self, i: usize) -> Self::Handle {
self.iter().nth(i).unwrap()
}
fn iter(&self) -> Box<dyn Iterator<Item = Value<'_, D>> + '_> {
let mut i = Box::new(ViewIterator::inner_new(&self.repr, self.value_range.start + 1));
fn iter(&self) -> Self::Items<'_> {
let mut i = ViewIterator::inner_new(&self.repr, self.value_range.start + 1);
match self.tag() {
Tag::Record => { i.next(); () }
Tag::Sequence => (),
@ -436,7 +441,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
self.tag() == Tag::Set
}
fn has(&self, v: &dyn ValueImpl<D>) -> bool {
fn has<E: ValueImpl<Embedded = Self::Embedded>>(&self, v: &E::Handle) -> bool {
self.iter().find(|e| v == &**e).is_some()
}
@ -444,36 +449,32 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
self.tag() == Tag::Dictionary
}
fn get(&self, k: &dyn ValueImpl<D>) -> Option<Value<'_, D>> {
fn get<K: ValueImpl<Embedded = Self::Embedded>>(&self, k: &K::Handle) -> Option<Self::Handle> {
for (kk, vv) in self.entries() {
if &*kk == k { return Some(vv); }
}
None
}
fn entries(&self) -> Box<dyn Iterator<Item = (Value<'_, D>, Value<'_, D>)> + '_> {
fn entries(&self) -> Self::Entries<'_> {
if !self.is_dictionary() { panic!("Not a dictionary") }
Box::new(DictionaryAdapter(ViewIterator::inner_new(&self.repr, self.value_range.start + 1)))
DictionaryAdapter(ViewIterator::inner_new(&self.repr, self.value_range.start + 1))
}
fn is_embedded(&self) -> bool {
self.tag() == Tag::Embedded
}
fn embedded(&self) -> Cow<'_, D> {
if !self.is_embedded() { panic!("Not an embedded value") }
fn as_embedded(&self) -> Option<Cow<'_, D>> {
if self.tag() != Tag::Embedded { return None }
match self.repr.index.embedded.as_ref() {
Some(e) => {
Cow::Borrowed(e.iter().find_map(|(r, d)| {
Some(Cow::Borrowed(e.iter().find_map(|(r, d)| {
if r.start == self.value_range.start { Some(d) } else { None }
}).unwrap())
}).unwrap()))
}
None => {
let mut r = BytesBinarySource::new(
&self.repr.packed.as_ref()[self.value_range.start + 1 .. self.value_range.end])
.into_packed();
let d = D::Decode::default().decode_embedded(&mut r, true).unwrap();
Cow::Owned(d)
Some(Cow::Owned(d))
}
}
}
@ -484,17 +485,38 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ValueImpl<D> for View<'de, Packe
} else {
let repr = Arc::new(IndexedRepr {
packed: self.repr.packed.as_ref(),
index: Index { embedded: None },
index: Index::<IOValue> { embedded: None },
phantom: PhantomData,
});
let anns: Vec<IOValue> = AnnotationAdapter(ViewIterator::inner_new(&repr, self.annotation_offset))
.map(|ann| iovalue(ann.into_owned()))
.collect();
Some(Cow::Owned(anns))
}
}
fn peeled(v: &Self::Handle) -> Self::Handle {
View {
repr: v.repr.clone(),
annotation_offset: v.value_range.start,
value_range: v.value_range,
}
}
fn copy<E: ValueImpl, F, Err>(w: &E::Handle, f: &mut F) -> Result<Self::Handle, Err>
where
F: FnMut(&E::Embedded) -> Result<Self::Handle, Err> {
todo!()
}
fn map_embedded<E: Domain, F, Err>(v: &Self::Handle, f: &mut F) -> Result<<Self::Mapped<E> as ValueImpl>::Handle, Err>
where
F: FnMut(&Self::Embedded) -> Result<E, Err> {
todo!()
}
}
crate::impl_value_methods!({'de, Packed: AsRef<[u8]> + 'de, D: Domain}, View<'de, Packed, D>);
pub struct ViewStream<'de, 'dec, D: Domain, Dec: DomainDecode<D> = <D as Domain>::Decode> {
buf: &'de [u8],
dec: Option<&'dec mut Dec>,
@ -514,7 +536,7 @@ impl<'de, 'dec, D: Domain, Dec: DomainDecode<D>> ViewStream<'de, 'dec, D, Dec> {
}
impl<'de, 'dec, D: Domain, Dec: DomainDecode<D>> Iterator for ViewStream<'de, 'dec, D, Dec> {
type Item = io::Result<Value<'de, D>>;
type Item = io::Result<View<'de, &'de [u8], D>>;
fn next(&mut self) -> Option<Self::Item> {
if self.offset >= self.buf.len() {
@ -523,7 +545,7 @@ impl<'de, 'dec, D: Domain, Dec: DomainDecode<D>> Iterator for ViewStream<'de, 'd
match View::new_offset(self.buf, self.dec.as_mut().map(|dec| &mut *dec), self.offset) {
Ok(v) => {
self.offset = v.value_range.end;
Some(Ok(shell(v)))
Some(Ok(v))
}
Err(e) => Some(Err(e)),
}
@ -543,7 +565,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> ViewIterator<IndexedRepr<'de, Pa
}
impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for ViewIterator<IndexedRepr<'de, Packed, D>> {
type Item = Value<'de, D>;
type Item = View<'de, Packed, D>;
fn next(&mut self) -> Option<Self::Item> {
if let Ok(Tag::End) = tag_at(self.repr.packed.as_ref(), self.offset) {
@ -551,7 +573,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for ViewIterator<Indexe
} else {
let v = View::inner_new(&self.repr, self.offset).unwrap();
self.offset = v.value_range.end;
Some(shell(v))
Some(v)
}
}
}
@ -559,7 +581,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for ViewIterator<Indexe
pub struct DictionaryAdapter<Repr>(pub ViewIterator<Repr>);
impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for DictionaryAdapter<IndexedRepr<'de, Packed, D>> {
type Item = (Value<'de, D>, Value<'de, D>);
type Item = (View<'de, Packed, D>, View<'de, Packed, D>);
fn next(&mut self) -> Option<Self::Item> {
let k = self.0.next()?;
@ -571,7 +593,7 @@ impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for DictionaryAdapter<I
pub struct AnnotationAdapter<Repr>(pub ViewIterator<Repr>);
impl<'de, Packed: AsRef<[u8]> + 'de, D: Domain> Iterator for AnnotationAdapter<IndexedRepr<'de, Packed, D>> {
type Item = Value<'de, D>;
type Item = View<'de, Packed, D>;
fn next(&mut self) -> Option<Self::Item> {
if let Ok(Tag::Annotation) = tag_at(self.0.repr.packed.as_ref(), self.0.offset) {

View File

@ -5,9 +5,11 @@ use std::marker::PhantomData;
use crate::BinarySource;
use crate::CompoundClass;
use crate::PlainValue;
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;
@ -17,13 +19,10 @@ use crate::error::ExpectedKind;
use crate::error::io_eof;
use crate::repr::Annotations;
use crate::repr::Atom;
use crate::repr::Embedded;
use crate::repr::IOValue;
use crate::repr::Map;
use crate::repr::Record;
use crate::repr::Set;
use crate::repr::ValueImpl;
use crate::repr::owned;
pub type ReaderResult<T> = std::result::Result<T, Error>;
@ -129,132 +128,24 @@ pub trait Reader<'de> {
}
}
fn gather_annotations(&mut self) -> io::Result<Option<(Vec<IOValue>, ValueClass)>> {
let mut anns = Vec::new();
loop {
match self.peek_class()? {
None => return Ok(None),
Some(NextToken::Value(v)) => return Ok(Some((anns, v))),
Some(NextToken::Annotation) => {
self.open_annotation()?;
anns.push(self.next_iovalue(true)?);
self.close_annotation()?;
}
}
}
}
fn next_boolean(&mut self) -> ReaderResult<bool> { Ok(self.next_atom()?.try_into()?)}
fn next_float(&mut self) -> ReaderResult<f32> { Ok(self.next_atom()?.try_into()?)}
fn next_double(&mut self) -> ReaderResult<f64> { Ok(self.next_atom()?.try_into()?)}
fn next_signedinteger(&mut self) -> ReaderResult<Cow<'de, SignedInteger>> { Ok(self.next_atom()?.try_into()?) }
fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> { Ok(self.next_atom()?.try_into()?) }
fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> { Ok(self.next_atom()?.try_into()?) }
fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> { Ok(self.next_atom()?.try_into_symbol()?) }
fn next<'produced: 'de, D: Domain, Dec: DomainDecode<D>>(
&mut self,
read_annotations: bool,
dec: &mut Dec,
) -> io::Result<PlainValue<'produced, D>>
{
let (anns, v) = match read_annotations {
true => self.gather_annotations()?.ok_or_else(io_eof)?,
false => (Vec::new(), self.skip_annotations()?.ok_or_else(io_eof)?),
};
let value = match v {
ValueClass::Atomic(_) =>
self.next_atom()?.into_value(),
ValueClass::Embedded => {
self.open_embedded()?;
let v = dec.decode_embedded(self, read_annotations)?;
self.close_embedded()?;
Box::new(Embedded::new(v))
}
ValueClass::Compound(CompoundClass::Record) => {
let mut vs = Vec::new();
self.open_record()?;
let mut b = B::start(B::Item::RecordLabel);
self.boundary(&b)?;
vs.push(self.next(read_annotations, dec)?);
while !self.close_compound(&mut b, &B::Item::RecordField)? {
vs.push(self.next(read_annotations, dec)?);
}
Box::new(Record::_from_vec(vs))
}
ValueClass::Compound(CompoundClass::Sequence) => {
let mut vs = Vec::new();
self.open_sequence()?;
let mut b = B::Type::default();
while !self.close_compound(&mut b, &B::Item::SequenceValue)? {
vs.push(self.next(read_annotations, dec)?);
}
Box::new(vs)
}
ValueClass::Compound(CompoundClass::Set) => {
let mut s = Set::new();
self.open_set()?;
let mut b = B::Type::default();
while !self.close_compound(&mut b, &B::Item::SetValue)? {
s.insert(self.next(read_annotations, dec)?);
}
Box::new(s)
}
ValueClass::Compound(CompoundClass::Dictionary) => {
let mut d = Map::new();
self.open_dictionary()?;
let mut b = B::Type::default();
while !self.close_compound(&mut b, &B::Item::DictionaryKey)? {
let k = self.next(read_annotations, dec)?;
b.shift(Some(B::Item::DictionaryValue));
self.boundary(&b)?;
d.insert(k, self.next(read_annotations, dec)?);
}
Box::new(d)
}
};
if anns.is_empty() {
Ok(value)
} else {
Ok(owned(Annotations::new(value, anns)))
}
}
fn next_iovalue(&mut self, read_annotations: bool) -> io::Result<IOValue>
{
Ok(self.next(read_annotations, &mut IOValueDomainCodec)?.into())
}
fn next_boolean(&mut self) -> ReaderResult<bool> {
self.next_iovalue(false)?.as_boolean().ok_or(Error::Expected(ExpectedKind::Boolean))
}
fn next_float(&mut self) -> ReaderResult<f32> {
self.next_iovalue(false)?.as_float().ok_or(Error::Expected(ExpectedKind::Float))
}
fn next_double(&mut self) -> ReaderResult<f64> {
self.next_iovalue(false)?.as_double().ok_or(Error::Expected(ExpectedKind::Double))
}
fn next_signedinteger(&mut self) -> ReaderResult<SignedInteger> {
self.next_iovalue(false)?.as_signed_integer().ok_or(Error::Expected(ExpectedKind::SignedInteger))
}
fn next_i8(&mut self) -> ReaderResult<i8> { Ok(i8::try_from(&self.next_signedinteger()?)?) }
fn next_u8(&mut self) -> ReaderResult<u8> { Ok(u8::try_from(&self.next_signedinteger()?)?) }
fn next_i16(&mut self) -> ReaderResult<i16> { Ok(i16::try_from(&self.next_signedinteger()?)?) }
fn next_u16(&mut self) -> ReaderResult<u16> { Ok(u16::try_from(&self.next_signedinteger()?)?) }
fn next_i32(&mut self) -> ReaderResult<i32> { Ok(i32::try_from(&self.next_signedinteger()?)?) }
fn next_u32(&mut self) -> ReaderResult<u32> { Ok(u32::try_from(&self.next_signedinteger()?)?) }
fn next_i64(&mut self) -> ReaderResult<i64> { Ok(i64::try_from(&self.next_signedinteger()?)?) }
fn next_u64(&mut self) -> ReaderResult<u64> { Ok(u64::try_from(&self.next_signedinteger()?)?) }
fn next_i128(&mut self) -> ReaderResult<i128> { Ok(i128::try_from(&self.next_signedinteger()?)?) }
fn next_u128(&mut self) -> ReaderResult<u128> { Ok(u128::try_from(&self.next_signedinteger()?)?) }
fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> {
Ok(self.next_iovalue(false)?.as_string().ok_or(Error::Expected(ExpectedKind::String))?.into_owned().into())
}
fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
Ok(self.next_iovalue(false)?.as_bytestring().ok_or(Error::Expected(ExpectedKind::ByteString))?.into_owned().into())
}
fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> {
Ok(self.next_iovalue(false)?.as_symbol().ok_or(Error::Expected(ExpectedKind::Symbol))?.into_owned().into())
}
fn next_i8(&mut self) -> ReaderResult<i8> { Ok(i8::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_u8(&mut self) -> ReaderResult<u8> { Ok(u8::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_i16(&mut self) -> ReaderResult<i16> { Ok(i16::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_u16(&mut self) -> ReaderResult<u16> { Ok(u16::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_i32(&mut self) -> ReaderResult<i32> { Ok(i32::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_u32(&mut self) -> ReaderResult<u32> { Ok(u32::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_i64(&mut self) -> ReaderResult<i64> { Ok(i64::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_u64(&mut self) -> ReaderResult<u64> { Ok(u64::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_i128(&mut self) -> ReaderResult<i128> { Ok(i128::try_from(self.next_signedinteger()?.as_ref())?) }
fn next_u128(&mut self) -> ReaderResult<u128> { Ok(u128::try_from(self.next_signedinteger()?.as_ref())?) }
fn open_simple_record(&mut self, name: &str) -> ReaderResult<B::Type>
{
@ -288,6 +179,97 @@ 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<Option<(Vec<IOValue>, 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<D>>(
r: &mut R,
read_annotations: bool,
dec: &mut Dec,
) -> io::Result<ShellHandle<'produced, D>> {
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<IOValue> {
Ok(read(r, read_annotations, &mut IOValueDomainCodec)?.into())
}
pub struct IOValues<'de, R: Reader<'de>> {
pub reader: R,
pub read_annotations: bool,
@ -315,7 +297,7 @@ impl<'de, R: Reader<'de>> std::iter::Iterator for IOValues<'de, R> {
match self.reader.peek_class() {
Err(e) => Some(Err(e)),
Ok(None) => None,
Ok(Some(_)) => Some(self.reader.next_iovalue(self.read_annotations)),
Ok(Some(_)) => Some(read_iovalue(&mut self.reader, self.read_annotations)),
}
}
}

View File

@ -1,38 +1,34 @@
use std::borrow::Borrow;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::collections::BTreeMap;
use std::collections::BTreeSet;
use std::hash::Hash;
use std::hash::Hasher;
use std::io;
use std::marker::PhantomData;
use std::ops::Deref;
use std::str::FromStr;
use std::sync::Arc;
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::AtomClass;
use crate::CompoundClass;
use crate::Domain;
use crate::DomainEncode;
use crate::SignedInteger;
use crate::ValueClass;
use crate::Writer;
use crate::boundary as B;
use crate::domain::{NoEmbeddedDomainCodec, DomainEncode, IOValueDomainCodec};
use crate::write_value;
use super::float::{eq_f32, eq_f64, cmp_f32, cmp_f64};
#[repr(transparent)]
pub struct Value<V: ValueImpl>(pub V);
/// Atomic values from the specification.
pub trait ValueImpl: Sized {
type Handle: Borrow<Self> + Clone + From<Self> + Hash + Eq + Ord + PartialEq + PartialOrd;
type Embedded: Domain;
type Mapped<E: Domain>: ValueImpl<Embedded = E>;
type Items<'a>: Iterator<Item = &'a Value<Self>> + 'a where Self: 'a;
type Entries<'a>: Iterator<Item = (&'a Value<Self>, &'a Value<Self>)> + 'a where Self: 'a;
type Items<'a>: Iterator<Item = Self::Handle> + 'a where Self: 'a;
type Entries<'a>: Iterator<Item = (Self::Handle, Self::Handle)> + 'a where Self: 'a;
type IOValueImpl: ValueImpl<Embedded = <Self::IOValueImpl as ValueImpl>::Handle>;
fn wrap(self) -> Self::Handle;
fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode<Self::Embedded>) -> io::Result<()> {
write_value(w, self, enc)
@ -62,778 +58,216 @@ pub trait ValueImpl: Sized {
fn as_usize(&self) -> Option<Result<usize, OutOfRange>> { self.as_signed_integer().map(|i| (&*i).try_into()) }
fn is_record(&self) -> bool;
fn label(&self) -> Value<Self>;
fn label(&self) -> Self::Handle;
fn is_sequence(&self) -> bool;
fn len(&self) -> usize;
fn index(&self, _i: usize) -> Value<Self>;
fn index(&self, _i: usize) -> Self::Handle;
fn iter(&self) -> Self::Items<'_>;
fn is_set(&self) -> bool;
fn has<E: ValueImpl<Embedded = Self::Embedded>>(&self, _v: &Value<E>) -> bool;
fn has<E: ValueImpl<Embedded = Self::Embedded>>(&self, _v: &E::Handle) -> bool;
fn is_dictionary(&self) -> bool;
fn get<K: ValueImpl<Embedded = Self::Embedded>>(&self, _k: &Value<K>) -> Option<Value<Self>>;
fn get<K: ValueImpl<Embedded = Self::Embedded>>(&self, _k: &K::Handle) -> Option<Self::Handle>;
fn entries(&self) -> Self::Entries<'_>;
fn as_embedded(&self) -> Option<Cow<'_, Self::Embedded>>;
// INVARIANT: return Some() *only* when the contained collection is nonempty
fn annotations(&self) -> Option<Cow<'_, [IOValue]>>;
fn annotations(&self) -> Option<Cow<'_, [<Self::IOValueImpl as ValueImpl>::Handle]>>;
fn peeled(&self) -> &Self;
fn peeled(v: &Self::Handle) -> Self::Handle;
fn copy<E: ValueImpl, F, Err>(w: &Value<E>, f: &mut F) -> Result<Value<Self>, Err>
fn copy<E: ValueImpl, F, Err>(w: &E::Handle, f: &mut F) -> Result<Self::Handle, Err>
where
F: FnMut(&E::Embedded) -> Result<Value<Self>, Err>;
F: FnMut(&E::Embedded) -> Result<Self::Handle, Err>;
fn map_embedded<E: Domain, F, Err>(&self, f: &mut F) -> Result<Value<Self::Mapped<E>>, Err>
fn map_embedded<E: Domain, F, Err>(v: &Self::Handle, f: &mut F) -> Result<<Self::Mapped<E> as ValueImpl>::Handle, Err>
where
F: FnMut(&Self::Embedded) -> Result<E, Err>;
}
impl<V: ValueImpl> Deref for Value<V> {
type Target = V;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<V: ValueImpl + Clone> Clone for Value<V> {
fn clone(&self) -> Self {
Value(self.0.clone())
}
}
impl<V: ValueImpl> Value<V> {
pub fn copy<W: ValueImpl, F, Err>(&self, f: &mut F) -> Result<Value<W>, Err>
where
F: FnMut(&V::Embedded) -> Result<Value<W>, Err>
{
W::copy(self, f)
}
}
impl<V: ValueImpl> Debug for Value<V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
TextWriter::fmt_value(f, &mut DefaultDomainCodec, self).map_err(|_| std::fmt::Error)
}
}
impl<Err: Into<io::Error>, D: Domain + FromStr<Err = Err>, V: ValueImpl<Embedded = D>>
FromStr for Value<V>
{
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(crate::annotated_from_str(s, &mut DefaultDomainCodec)?.value_clone())
}
}
impl<V: ValueImpl> Hash for Value<V> {
fn hash<H: Hasher>(&self, state: &mut H) {
match self.value_class() {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean => self.as_boolean().unwrap().hash(state),
AtomClass::Float => self.as_float().unwrap().to_bits().hash(state),
AtomClass::Double => self.as_double().unwrap().to_bits().hash(state),
AtomClass::SignedInteger => self.as_signed_integer().unwrap().hash(state),
AtomClass::String => self.as_string().unwrap().hash(state),
AtomClass::ByteString => self.as_bytestring().unwrap().hash(state),
AtomClass::Symbol => self.as_symbol().unwrap().hash(state),
}
ValueClass::Compound(c) => match c {
CompoundClass::Sequence |
CompoundClass::Set => {
state.write_usize(self.len());
for v in self.iter() { v.hash(state) }
}
CompoundClass::Record => {
self.label().hash(state);
state.write_usize(self.len());
for v in self.iter() { v.hash(state) }
}
CompoundClass::Dictionary => {
state.write_usize(self.len());
for (k, v) in self.entries() {
k.hash(state);
v.hash(state);
}
}
}
ValueClass::Embedded => self.as_embedded().unwrap().hash(state),
pub fn value_hash<V: ValueImpl, H: Hasher>(v: &V, state: &mut H) {
match v.value_class() {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean => v.as_boolean().unwrap().hash(state),
AtomClass::Float => v.as_float().unwrap().to_bits().hash(state),
AtomClass::Double => v.as_double().unwrap().to_bits().hash(state),
AtomClass::SignedInteger => v.as_signed_integer().unwrap().hash(state),
AtomClass::String => v.as_string().unwrap().hash(state),
AtomClass::ByteString => v.as_bytestring().unwrap().hash(state),
AtomClass::Symbol => v.as_symbol().unwrap().hash(state),
}
}
}
impl<V: ValueImpl> PartialEq for Value<V> {
fn eq(&self, other: &Self) -> bool {
let cls = self.value_class();
if cls != other.value_class() { return false; }
match cls {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean =>
self.as_boolean().unwrap() == other.as_boolean().unwrap(),
AtomClass::Float =>
eq_f32(self.as_float().unwrap(), other.as_float().unwrap()),
AtomClass::Double =>
eq_f64(self.as_double().unwrap(), other.as_double().unwrap()),
AtomClass::SignedInteger =>
self.as_signed_integer().unwrap() == other.as_signed_integer().unwrap(),
AtomClass::String =>
self.as_string().unwrap() == other.as_string().unwrap(),
AtomClass::ByteString =>
self.as_bytestring().unwrap() == other.as_bytestring().unwrap(),
AtomClass::Symbol =>
self.as_symbol().unwrap() == other.as_symbol().unwrap(),
ValueClass::Compound(c) => match c {
CompoundClass::Sequence |
CompoundClass::Set => {
state.write_usize(v.len());
for v in v.iter() { v.hash(state) }
}
ValueClass::Compound(c) => match c {
CompoundClass::Record => {
if self.label() != other.label() { return false; }
self.iter().eq(other.iter())
}
CompoundClass::Sequence => {
self.iter().eq(other.iter())
}
CompoundClass::Set => {
let s1 = self.iter().collect::<Set<_>>();
let s2 = other.iter().collect::<Set<_>>();
s1 == s2
}
CompoundClass::Dictionary => {
let d1 = self.entries().collect::<Map<_, _>>();
let d2 = other.entries().collect::<Map<_, _>>();
d1 == d2
CompoundClass::Record => {
v.label().hash(state);
state.write_usize(v.len());
for v in v.iter() { v.hash(state) }
}
CompoundClass::Dictionary => {
state.write_usize(v.len());
for (k, v) in v.entries() {
k.hash(state);
v.hash(state);
}
}
ValueClass::Embedded => self.as_embedded().unwrap() == other.as_embedded().unwrap(),
}
ValueClass::Embedded => v.as_embedded().unwrap().hash(state),
}
}
impl<V: ValueImpl> Ord for Value<V> {
fn cmp(&self, other: &Self) -> Ordering {
let cls = self.value_class();
cls.cmp(&other.value_class()).then_with(|| match cls {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean =>
self.as_boolean().cmp(&other.as_boolean()),
AtomClass::Float =>
cmp_f32(self.as_float().unwrap(), other.as_float().unwrap()),
AtomClass::Double =>
cmp_f64(self.as_double().unwrap(), other.as_double().unwrap()),
AtomClass::SignedInteger =>
self.as_signed_integer().cmp(&other.as_signed_integer()),
AtomClass::String =>
self.as_string().cmp(&other.as_string()),
AtomClass::ByteString =>
self.as_bytestring().cmp(&other.as_bytestring()),
AtomClass::Symbol =>
self.as_symbol().cmp(&other.as_symbol()),
},
ValueClass::Compound(c) => match c {
CompoundClass::Record =>
self.label().cmp(&other.label()).then_with(
|| self.iter().cmp(other.iter())),
CompoundClass::Sequence => self.iter().cmp(other.iter()),
CompoundClass::Set => {
let s1 = self.iter().collect::<Set<_>>();
let s2 = other.iter().collect::<Set<_>>();
s1.cmp(&s2)
}
CompoundClass::Dictionary => {
let d1 = self.entries().collect::<Map<_, _>>();
let d2 = other.entries().collect::<Map<_, _>>();
d1.cmp(&d2)
}
},
ValueClass::Embedded => self.as_embedded().unwrap().cmp(&other.as_embedded().unwrap()),
})
}
}
impl<V: ValueImpl> Eq for Value<V> {}
impl<V: ValueImpl> PartialOrd for Value<V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Debug, Clone)]
pub enum Atom<'a> {
Boolean(bool),
Float(f32),
Double(f64),
SignedInteger(Cow<'a, SignedInteger>),
String(Cow<'a, str>),
ByteString(Cow<'a, [u8]>),
Symbol(Cow<'a, str>),
}
impl<'a> Atom<'a> {
fn write(&self, w: &mut dyn Writer) -> 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 symbol<W: Into<Cow<'a, str>>>(v: W) -> Self {
Atom::Symbol(v.into())
}
}
impl<'r, 'a> From<&'r Atom<'a>> for AtomClass {
fn from(a: &'r Atom<'a>) -> Self {
match a {
Atom::Boolean(_) => AtomClass::Boolean,
Atom::Float(_) => AtomClass::Float,
Atom::Double(_) => AtomClass::Double,
Atom::SignedInteger(_) => AtomClass::SignedInteger,
Atom::String(_) => AtomClass::String,
Atom::ByteString(_) => AtomClass::ByteString,
Atom::Symbol(_) => AtomClass::Symbol,
}
}
}
impl<'a> From<bool> for Atom<'a> { fn from(v: bool) -> Self { Atom::Boolean(v) } }
impl<'a> From<f32> for Atom<'a> { fn from(v: f32) -> Self { Atom::Float(v) } }
impl<'a> From<f64> 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<SignedInteger> 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<String> 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<Vec<u8>> for Atom<'a> { fn from(v: Vec<u8>) -> Self { Atom::ByteString(Cow::Owned(v)) } }
// #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
// pub enum NoValue {}
// impl Domain for NoValue {
// type Decode = NoEmbeddedDomainCodec;
// type Encode = NoEmbeddedDomainCodec;
// }
// impl FromStr for NoValue {
// type Err = io::Error;
// fn from_str(_s: &str) -> Result<Self, Self::Err> {
// Err(io::Error::new(io::ErrorKind::Unsupported, "Embedded values not supported here"))
// }
// }
// pub struct NoIterator<A> {
// nothing: NoValue,
// phantom: PhantomData<A>,
// }
// impl<A> Iterator for NoIterator<A> {
// type Item = A;
// fn next(&mut self) -> Option<Self::Item> {
// None
// }
// }
// impl ValueImpl for NoValue {
// type Embedded = NoValue;
// type Mapped<_E: Domain> = NoValue;
// type Items<'a> = NoIterator<&'a Value<Self>>;
// type Entries<'a> = NoIterator<(&'a Value<Self>, &'a Value<Self>)>;
// fn write(&self, _w: &mut dyn Writer, _enc: &mut dyn DomainEncode<Self::Embedded>) -> io::Result<()> { unreachable!() }
// fn value_class(&self) -> ValueClass { unreachable!() }
// fn as_boolean(&self) -> Option<bool> { unreachable!() }
// fn as_float(&self) -> Option<f32> { unreachable!() }
// fn as_double(&self) -> Option<f64> { unreachable!() }
// fn as_signed_integer(&self) -> Option<Cow<'_, SignedInteger>> { unreachable!() }
// fn as_string(&self) -> Option<Cow<'_, str>> { unreachable!() }
// fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> { unreachable!() }
// fn as_symbol(&self) -> Option<Cow<'_, str>> { unreachable!() }
// fn is_record(&self) -> bool { unreachable!() }
// fn label(&self) -> Value<Self> { unreachable!() }
// fn is_sequence(&self) -> bool { unreachable!() }
// fn len(&self) -> usize { unreachable!() }
// fn index(&self, _i: usize) -> Value<Self> { unreachable!() }
// fn iter(&self) -> Self::Items<'_> { unreachable!() }
// fn is_set(&self) -> bool { unreachable!() }
// fn has<E: ValueImpl<Embedded = Self::Embedded>>(&self, _v: &Value<E>) -> bool { unreachable!() }
// fn is_dictionary(&self) -> bool { unreachable!() }
// fn get<K: ValueImpl<Embedded = Self::Embedded>>(&self, _k: &Value<K>) -> Option<Value<Self>> { unreachable!() }
// fn entries(&self) -> Self::Entries<'_> { unreachable!() }
// fn as_embedded(&self) -> Option<Cow<'_, Self::Embedded>> { unreachable!() }
// fn annotations(&self) -> Option<Cow<'_, [IOValue]>> { unreachable!() }
// fn peeled(&self) -> &Self { unreachable!() }
// fn copy<E: ValueImpl, F, Err>(w: &Value<E>, f: &mut F) -> Result<Value<Self>, Err>
// where
// F: FnMut(&E::Embedded) -> Result<Value<Self>, Err>
// {
// panic!("Cannot copy into NoValue")
// }
// fn map_embedded<E: Domain, F, Err>(&self, f: &mut F) -> Result<Value<Self::Mapped<E>>, Err>
// where
// F: FnMut(&Self::Embedded) -> Result<E, Err>
// {
// unreachable!()
// }
// }
pub enum Shell<'a, V: ValueImpl> {
Atom(Atom<'a>),
Record(Record<Value<V>>),
Sequence(Vec<Value<V>>),
Set(Set<Value<V>>),
Dictionary(Map<Value<V>, Value<V>>),
Embedded(V::Embedded),
Annotated(Annotations<V>),
}
impl<D: Domain> Shell<'static, Arc<ArcValueImpl<D>>> {
pub fn record(label: ArcValue<D>, fields: Vec<ArcValue<D>>) -> ArcValue<D> {
Value(Arc::new(ArcValueImpl(Shell::Record(Record::new(label, fields)), PhantomData)))
}
}
impl<'a, V: ValueImpl> ValueImpl for Shell<'a, V> {
type Embedded = V::Embedded;
type Mapped<E: Domain> = Shell<'a, V::Mapped<E>>;
type Items<'i> = std::slice::Iter<'i, Value<Self>> where Self: 'i;
type Entries<'i> = std::collections::btree_map::Iter<'i, Value<Self>, Value<Self>> where Self: 'i;
fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode<V::Embedded>) -> 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.0.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()
// TODO: when unstable feature iter_order_by stabilises, use that instead
fn iters_eq<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(i: &V::Items<'_>, j: &W::Items<'_>) -> bool {
loop {
match i.next() {
None => return j.next().is_none(),
Some(ii) => match j.next() {
None => return false,
Some(jj) => if !value_eq(ii.borrow(), jj.borrow()) { return false },
}
}
}
}
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(),
pub fn value_eq<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(v: &V, w: &W) -> bool {
let cls = v.value_class();
if cls != w.value_class() { return false; }
match cls {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean =>
v.as_boolean().unwrap() == w.as_boolean().unwrap(),
AtomClass::Float =>
eq_f32(v.as_float().unwrap(), w.as_float().unwrap()),
AtomClass::Double =>
eq_f64(v.as_double().unwrap(), w.as_double().unwrap()),
AtomClass::SignedInteger =>
v.as_signed_integer().unwrap() == w.as_signed_integer().unwrap(),
AtomClass::String =>
v.as_string().unwrap() == w.as_string().unwrap(),
AtomClass::ByteString =>
v.as_bytestring().unwrap() == w.as_bytestring().unwrap(),
AtomClass::Symbol =>
v.as_symbol().unwrap() == w.as_symbol().unwrap(),
}
}
fn copy<E: ValueImpl, F, Err>(w: &Value<E>, f: &mut F) -> Result<Value<Self>, Err>
where
F: FnMut(&E::Embedded) -> Result<Value<Self>, Err>
{
let r: Self = 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::<Result<Vec<_>, _>>()?),
CompoundClass::Set =>
Shell::Set(w.iter().map(|ww| ww.copy(f)).collect::<Result<Set<_>, _>>()?),
CompoundClass::Record =>
Shell::Record(Record::new(
w.label().copy(f)?,
w.iter().map(|ww| ww.copy(f)).collect::<Result<Vec<_>, _>>()?)),
CompoundClass::Dictionary =>
Shell::Dictionary(w.entries().map(|(k, ww)| Ok((k.copy(f)?, ww.copy(f)?)))
.collect::<Result<Map<_, _>, _>>()?),
},
ValueClass::Embedded => f(&w.as_embedded().unwrap())?.0,
};
if let Some(anns) = w.annotations() {
Ok(Value(Shell::Annotated(Annotations(Box::new((Value(r), anns.into_owned().into()))))))
} else {
Ok(Value(r))
ValueClass::Compound(c) => match c {
CompoundClass::Record => {
if !value_eq(v.label().borrow(), w.label().borrow()) { return false; }
iters_eq::<V, W>(&v.iter(), &w.iter())
}
CompoundClass::Sequence => {
iters_eq::<V, W>(&v.iter(), &w.iter())
}
CompoundClass::Set => {
let s1 = v.iter().collect::<BTreeSet<_>>();
let s2 = w.iter().collect::<BTreeSet<_>>();
todo!() // s1 == s2
}
CompoundClass::Dictionary => {
let d1 = v.entries().collect::<BTreeMap<_, _>>();
let d2 = w.entries().collect::<BTreeMap<_, _>>();
todo!() // d1 == d2
}
}
ValueClass::Embedded => v.as_embedded().unwrap() == w.as_embedded().unwrap(),
}
}
fn map_embedded<E: Domain, F, Err>(&self, f: &mut F) -> Result<Value<Self::Mapped<E>>, Err>
where
F: FnMut(&V::Embedded) -> Result<E, Err>
{
Self::Mapped::<E>::copy(&Value(*self), &mut |d| Ok(Value(Self::Mapped::<E>::Embedded(f(d)?))))
}
fn as_boolean(&self) -> Option<bool> {
match self {
Shell::Atom(Atom::Boolean(b)) => Some(*b),
_ => None,
}
}
fn as_float(&self) -> Option<f32> {
match self {
Shell::Atom(Atom::Float(f)) => Some(*f),
_ => None,
}
}
fn as_double(&self) -> Option<f64> {
match self {
Shell::Atom(Atom::Double(d)) => Some(*d),
_ => None,
}
}
fn as_signed_integer(&self) -> Option<Cow<'_, SignedInteger>> {
match self {
Shell::Atom(Atom::SignedInteger(i)) => Some(Cow::Borrowed(i)),
_ => None,
}
}
fn as_string(&self) -> Option<Cow<'_, str>> {
match self {
Shell::Atom(Atom::String(s)) => Some(Cow::Borrowed(s)),
_ => None,
}
}
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> {
match self {
Shell::Atom(Atom::ByteString(bs)) => Some(Cow::Borrowed(bs)),
_ => None,
}
}
fn as_symbol(&self) -> Option<Cow<'_, str>> {
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<Self> {
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<Self> {
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<E: ValueImpl<Embedded = V::Embedded>>(&self, v: &Value<E>) -> bool {
match self {
Shell::Set(items) => items.contains(v),
_ => false,
}
}
fn is_dictionary(&self) -> bool {
matches!(self, Shell::Dictionary(_))
}
fn get<K: ValueImpl<Embedded = V::Embedded>>(&self, k: &Value<K>) -> Option<Value<Self>> {
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<Cow<'_, V::Embedded>> {
match self {
Shell::Embedded(d) => Some(Cow::Borrowed(d)),
_ => None,
}
}
fn annotations(&self) -> Option<Cow<'_, [IOValue]>> {
match self {
Shell::Annotated(b) => Some(Cow::Borrowed(&b.1)),
_ => None,
}
}
fn peeled(&self) -> &Self {
match self {
Shell::Annotated(b) => Some(b.0),
_ => self,
// TODO: when unstable feature iter_order_by stabilises, use that instead
fn iters_cmp<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(i: &V::Items<'_>, j: &W::Items<'_>) -> Ordering {
loop {
match i.next() {
None => return if j.next().is_none() { Ordering::Equal } else { Ordering::Less },
Some(ii) => match j.next() {
None => return Ordering::Greater,
Some(jj) => {
let r = value_cmp(ii.borrow(), jj.borrow());
if !r.is_eq() { return r }
}
}
}
}
}
impl<V: ValueImpl> From<V> for Value<V> {
fn from(v: V) -> Self {
Value(v)
}
pub fn value_cmp<V: ValueImpl, W: ValueImpl<Embedded = V::Embedded>>(v: &V, w: &W) -> Ordering {
let cls = v.value_class();
cls.cmp(&w.value_class()).then_with(|| match cls {
ValueClass::Atomic(a) => match a {
AtomClass::Boolean =>
v.as_boolean().cmp(&w.as_boolean()),
AtomClass::Float =>
cmp_f32(v.as_float().unwrap(), w.as_float().unwrap()),
AtomClass::Double =>
cmp_f64(v.as_double().unwrap(), w.as_double().unwrap()),
AtomClass::SignedInteger =>
v.as_signed_integer().cmp(&w.as_signed_integer()),
AtomClass::String =>
v.as_string().cmp(&w.as_string()),
AtomClass::ByteString =>
v.as_bytestring().cmp(&w.as_bytestring()),
AtomClass::Symbol =>
v.as_symbol().cmp(&w.as_symbol()),
},
ValueClass::Compound(c) => match c {
CompoundClass::Record =>
value_cmp(v.label().borrow(), w.label().borrow()).then_with(
|| iters_cmp::<V, W>(&v.iter(), &w.iter())),
CompoundClass::Sequence => iters_cmp::<V, W>(&v.iter(), &w.iter()),
CompoundClass::Set => {
let s1 = v.iter().collect::<Set<_>>();
let s2 = w.iter().collect::<Set<_>>();
todo!() // s1.cmp(&s2)
}
CompoundClass::Dictionary => {
let d1 = v.entries().collect::<Map<_, _>>();
let d2 = w.entries().collect::<Map<_, _>>();
todo!() // d1.cmp(&d2)
}
},
ValueClass::Embedded => v.as_embedded().unwrap().cmp(&w.as_embedded().unwrap()),
})
}
impl<'a, W: Into<Atom<'a>>, V: ValueImpl> From<W> for Shell<'a, V> {
fn from(w: W) -> Self {
Shell::Atom(w.into())
}
#[macro_export]
macro_rules! impl_value_methods {
({ $($gdecls:tt)* }, $t:ty) => {
impl< $($gdecls)* > std::fmt::Debug for $t {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
crate::TextWriter::fmt_value(f, &mut crate::DefaultDomainCodec, self)
.map_err(|_| std::fmt::Error)
}
}
impl< $($gdecls)* > PartialEq for $t {
fn eq(&self, other: &Self) -> bool {
crate::value_eq(self, other)
}
}
impl< $($gdecls)* > Eq for $t {}
impl< $($gdecls)* > PartialOrd for $t {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(crate::value_cmp(self, other))
}
}
impl< $($gdecls)* > Ord for $t {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
crate::value_cmp(self, other)
}
}
impl< $($gdecls)* > std::hash::Hash for $t {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
crate::value_hash(self, state)
}
}
};
}
impl<'a, V: ValueImpl> From<Vec<Value<V>>> for Shell<'a, V> {
fn from(vs: Vec<Value<V>>) -> Self {
Shell::Sequence(vs)
}
}
impl<'a, V: ValueImpl> From<Set<Value<V>>> for Shell<'a, V> {
fn from(vs: Set<Value<V>>) -> Self {
Shell::Set(vs)
}
}
impl<'a, V: ValueImpl> From<Map<Value<V>, Value<V>>> for Shell<'a, V> {
fn from(vs: Map<Value<V>, Value<V>>) -> Self {
Shell::Dictionary(vs)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Record<V>(Vec<V> /* at least one element, for the label */);
impl<V> Record<V> {
pub fn new(label: V, mut fields: Vec<V>) -> Self {
fields.insert(0, label);
Record(fields)
}
pub fn _from_vec(v: Vec<V>) -> Self {
if v.is_empty() { panic!("Internal error: empty vec supplied to Record::_from_vec") }
Record(v)
}
pub fn _vec(&self) -> &Vec<V> {
&self.0
}
}
#[derive(Clone)]
pub struct Annotations<V: ValueImpl>(Box<(Value<V>, Vec<IOValue>)>);
impl<V: ValueImpl> Hash for Annotations<V> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.as_ref().0.hash(state)
}
}
impl<V: ValueImpl> PartialEq for Annotations<V> {
fn eq(&self, other: &Self) -> bool {
self.0.as_ref().0.eq(other.0.as_ref().0)
}
}
impl<V: ValueImpl> Ord for Annotations<V> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.as_ref().0.cmp(other.0.as_ref().0)
}
}
impl<V: ValueImpl> Eq for Annotations<V> {}
impl<V: ValueImpl> PartialOrd for Annotations<V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct ArcValueImpl<D: Domain>(Shell<'static, Arc<ArcValueImpl<D>>>, PhantomData<D>);
pub type ArcValue<D> = Value<Arc<ArcValueImpl<D>>>;
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct IOValueImpl(ArcValueImpl<IOValue>);
pub type IOValue = Value<Arc<IOValueImpl>>;
unsafe impl bytemuck::TransparentWrapper<ArcValueImpl<IOValue>> for IOValueImpl {}
impl From<ArcValue<IOValue>> for IOValue {
fn from(v: ArcValue<IOValue>) -> Self {
IOValue::wrap_arc(v)
}
}
impl From<IOValue> for ArcValue<IOValue> {
fn from(v: IOValue) -> Self {
IOValue::peel_arc(v)
}
}
impl<D: Domain> ValueImpl for ArcValueImpl<D> {
}
impl ValueImpl for IOValueImpl {
}
impl<V: ValueImpl> ValueImpl for Arc<V> {
}
// impl<D: Domain> Debug for ArcValue<D> {
// 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<D: Domain> PartialEq for ArcValue<D> {
// fn eq(&self, other: &Self) -> bool {
// &self.0 == &other.0
// }
// }
// impl<Err: Into<io::Error>, D: Domain + FromStr<Err = Err>> FromStr for ArcValue<D> {
// type Err = io::Error;
// fn from_str(s: &str) -> Result<Self, Self::Err> {
// 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<Self, Self::Err> {
// crate::annotated_iovalue_from_str(s)
// }
// }
// impl<D: Domain> From<PlainValue<'static, D>> for ArcValue<D> {
// fn from(b: PlainValue<'static, D>) -> Self {
// ArcValue(Arc::from(b))
// }
// }
// impl From<PlainValue<'static, IOValue>> for IOValue {
// fn from(b: PlainValue<'static, IOValue>) -> Self {
// IOValue(b.into())
// }
// }
// impl From<ArcValue<IOValue>> for IOValue {
// fn from(b: ArcValue<IOValue>) -> Self {
// IOValue(b)
// }
// }

View File

@ -0,0 +1,714 @@
use std::borrow::Borrow;
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt::Debug;
use std::hash::Hash;
use std::hash::Hasher;
use std::io;
use std::str::FromStr;
use std::sync::Arc;
use bytemuck::TransparentWrapper;
use crate::AtomClass;
use crate::CompoundClass;
use crate::Domain;
use crate::DomainEncode;
use crate::ExpectedKind;
use crate::IOValueDomainCodec;
use crate::SignedInteger;
use crate::ValueClass;
use crate::ValueImpl;
use crate::Writer;
use crate::boundary as B;
use crate::impl_value_methods;
pub use std::collections::BTreeSet as Set;
pub use std::collections::BTreeMap as Map;
#[derive(Debug, Clone)]
pub enum Atom<'a> {
Boolean(bool),
Float(f32),
Double(f64),
SignedInteger(Cow<'a, SignedInteger>),
String(Cow<'a, str>),
ByteString(Cow<'a, [u8]>),
Symbol(Cow<'a, str>),
}
impl<'a> Atom<'a> {
pub fn write(&self, w: &mut dyn Writer) -> 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),
}
}
pub fn symbol<W: Into<Cow<'a, str>>>(v: W) -> Self {
Atom::Symbol(v.into())
}
pub fn try_into_symbol(self) -> Result<Cow<'a, str>, ExpectedKind> {
match self {
Atom::Symbol(s) => Ok(s),
_ => Err(ExpectedKind::Symbol),
}
}
pub fn as_symbol(self) -> Result<&'a str, ExpectedKind> {
match self {
Atom::Symbol(s) => Ok(s.as_ref()),
_ => Err(ExpectedKind::Symbol),
}
}
}
impl<'r, 'a> From<&'r Atom<'a>> for AtomClass {
fn from(a: &'r Atom<'a>) -> Self {
match a {
Atom::Boolean(_) => AtomClass::Boolean,
Atom::Float(_) => AtomClass::Float,
Atom::Double(_) => AtomClass::Double,
Atom::SignedInteger(_) => AtomClass::SignedInteger,
Atom::String(_) => AtomClass::String,
Atom::ByteString(_) => AtomClass::ByteString,
Atom::Symbol(_) => AtomClass::Symbol,
}
}
}
impl<'a> From<bool> for Atom<'a> { fn from(v: bool) -> Self { Atom::Boolean(v) } }
impl<'a> From<f32> for Atom<'a> { fn from(v: f32) -> Self { Atom::Float(v) } }
impl<'a> From<f64> 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<SignedInteger> 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<String> 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<Vec<u8>> for Atom<'a> { fn from(v: Vec<u8>) -> Self { Atom::ByteString(Cow::Owned(v)) } }
macro_rules! from_atom_ref_impl {
($t:ty, $p:pat, $e:expr, $err:expr) => {
impl<'r, 'a> TryFrom<&'r Atom<'a>> for $t {
type Error = ExpectedKind;
fn try_from(value: &'r Atom<'a>) -> Result<Self, Self::Error> {
match value {
$p => Ok($e),
_ => Err($err),
}
}
}
};
}
from_atom_ref_impl!(bool, Atom::Boolean(b), *b, ExpectedKind::Boolean);
from_atom_ref_impl!(f32, Atom::Float(f), *f, ExpectedKind::Float);
from_atom_ref_impl!(f64, Atom::Double(d), *d, ExpectedKind::Double);
from_atom_ref_impl!(&'a SignedInteger, Atom::SignedInteger(i), i.as_ref(), ExpectedKind::SignedInteger);
from_atom_ref_impl!(&'a str, Atom::String(s), s.as_ref(), ExpectedKind::String);
from_atom_ref_impl!(&'a [u8], Atom::ByteString(bs), bs.as_ref(), ExpectedKind::ByteString);
macro_rules! from_atom_val_impl {
($t:ty, $p:pat, $e:expr, $err:expr) => {
impl<'a> TryFrom<Atom<'a>> for $t {
type Error = ExpectedKind;
fn try_from(value: Atom<'a>) -> Result<Self, Self::Error> {
match value {
$p => Ok($e),
_ => Err($err),
}
}
}
};
}
from_atom_val_impl!(bool, Atom::Boolean(b), b, ExpectedKind::Boolean);
from_atom_val_impl!(f32, Atom::Float(f), f, ExpectedKind::Float);
from_atom_val_impl!(f64, Atom::Double(d), d, ExpectedKind::Double);
from_atom_val_impl!(Cow<'a, SignedInteger>, Atom::SignedInteger(i), i, ExpectedKind::SignedInteger);
from_atom_val_impl!(Cow<'a, str>, Atom::String(s), s, ExpectedKind::String);
from_atom_val_impl!(Cow<'a, [u8]>, Atom::ByteString(bs), bs, ExpectedKind::ByteString);
pub type ShellHandle<'a, D> = Arc<Shell<'a, D>>;
pub enum Shell<'a, D: Domain> {
Atom(Atom<'a>),
Record(Record<ShellHandle<'a, D>>),
Sequence(Vec<ShellHandle<'a, D>>),
Set(Set<ShellHandle<'a, D>>),
Dictionary(Map<ShellHandle<'a, D>, ShellHandle<'a, D>>),
Embedded(D),
Annotated(Annotations<Self>),
}
impl<'a, D: Domain> Shell<'a, D> {
pub fn record(label: ShellHandle<'a, D>, fields: Vec<ShellHandle<'a, D>>) -> Self {
Shell::Record(Record::new(label, fields))
}
pub fn symbol<S: Into<Cow<'a, str>>>(s: S) -> Self {
Shell::Atom(Atom::symbol(s))
}
pub fn embedded(d: D) -> Self {
Shell::Embedded(d)
}
}
impl<'a, D: Domain> ValueImpl for Shell<'a, D> {
type Handle = ShellHandle<'a, D>;
type Embedded = D;
type Mapped<E: Domain> = 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;
fn wrap(self) -> Self::Handle {
Self::Handle::new(self)
}
fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode<D>) -> 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.0.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.value().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()
}
}
}
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.as_ref().0.value_class(),
}
}
fn copy<E: ValueImpl, F, Err>(w: &E::Handle, f: &mut F) -> Result<Self::Handle, Err>
where
F: FnMut(&E::Embedded) -> Result<Self::Handle, Err>
{
let w = w.borrow();
let r: Self::Handle = 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())),
}.wrap(),
ValueClass::Compound(c) => match c {
CompoundClass::Sequence =>
Shell::Sequence(w.iter().map(|ww| Self::copy::<E, _, _>(&ww, f)).collect::<Result<Vec<_>, _>>()?),
CompoundClass::Set =>
Shell::Set(w.iter().map(|ww| Self::copy::<E, _, _>(&ww, f)).collect::<Result<Set<_>, _>>()?),
CompoundClass::Record =>
Shell::Record(Record::new(
Self::copy::<E, _, _>(&w.label(), f)?,
w.iter().map(|ww| Self::copy::<E, _, _>(&ww, f)).collect::<Result<Vec<_>, _>>()?)),
CompoundClass::Dictionary =>
Shell::Dictionary(
w.entries().map(|(k, ww)| Ok((Self::copy::<E, _, _>(&k, f)?,
Self::copy::<E, _, _>(&ww, f)?)))
.collect::<Result<Map<_, _>, _>>()?),
}.wrap(),
ValueClass::Embedded => f(&w.as_embedded().unwrap())?
};
if let Some(anns) = w.annotations() {
Ok(Shell::Annotated(Annotations(Box::new((
r,
anns.iter().map(copy_iovalue::<E::IOValueImpl>).collect()
)))).wrap())
} else {
Ok(r)
}
}
fn map_embedded<E: Domain, F, Err>(v: &Self::Handle, f: &mut F) -> Result<<Self::Mapped<E> as ValueImpl>::Handle, Err>
where
F: FnMut(&D) -> Result<E, Err>
{
Self::Mapped::<E>::copy::<Self, _, _>(v, &mut |d| Ok(
ShellHandle::<'a, E>::new(Self::Mapped::<E>::Embedded(f(d)?))))
}
fn as_boolean(&self) -> Option<bool> {
match self {
Shell::Atom(Atom::Boolean(b)) => Some(*b),
_ => None,
}
}
fn as_float(&self) -> Option<f32> {
match self {
Shell::Atom(Atom::Float(f)) => Some(*f),
_ => None,
}
}
fn as_double(&self) -> Option<f64> {
match self {
Shell::Atom(Atom::Double(d)) => Some(*d),
_ => None,
}
}
fn as_signed_integer(&self) -> Option<Cow<'_, SignedInteger>> {
match self {
Shell::Atom(Atom::SignedInteger(i)) => Some(Cow::Borrowed(i)),
_ => None,
}
}
fn as_string(&self) -> Option<Cow<'_, str>> {
match self {
Shell::Atom(Atom::String(s)) => Some(Cow::Borrowed(s)),
_ => None,
}
}
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> {
match self {
Shell::Atom(Atom::ByteString(bs)) => Some(Cow::Borrowed(bs)),
_ => None,
}
}
fn as_symbol(&self) -> Option<Cow<'_, str>> {
match self {
Shell::Atom(Atom::Symbol(s)) => Some(Cow::Borrowed(s)),
_ => None,
}
}
fn is_record(&self) -> bool {
matches!(self, Shell::Record(_))
}
fn label(&self) -> Self::Handle {
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) -> Self::Handle {
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<E: ValueImpl<Embedded = D>>(&self, v: &E::Handle) -> bool {
match self {
Shell::Set(items) => todo!(), // items.contains(v),
_ => false,
}
}
fn is_dictionary(&self) -> bool {
matches!(self, Shell::Dictionary(_))
}
fn get<K: ValueImpl<Embedded = D>>(&self, k: &K::Handle) -> Option<Self::Handle> {
match self {
Shell::Dictionary(entries) => todo!(), // 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<Cow<'_, D>> {
match self {
Shell::Embedded(d) => Some(Cow::Borrowed(d)),
_ => None,
}
}
fn annotations(&self) -> Option<Cow<'_, [<Self::IOValueImpl as ValueImpl>::Handle]>> {
match self {
Shell::Annotated(b) => Some(Cow::Borrowed(&b.0.as_ref().1)),
_ => None,
}
}
fn peeled(v: &Self::Handle) -> Self::Handle {
match v.as_ref() {
Shell::Annotated(b) => b.0.0,
_ => v.clone(),
}
}
}
impl_value_methods!({'a, D: Domain}, Shell<'a, D>);
impl<'a, W: Into<Atom<'a>>, D: Domain> From<W> for Shell<'a, D> {
fn from(w: W) -> Self {
Shell::Atom(w.into())
}
}
impl<'a, D: Domain> From<Vec<ShellHandle<'a, D>>> for Shell<'a, D> {
fn from(vs: Vec<ShellHandle<'a, D>>) -> Self {
Shell::Sequence(vs)
}
}
impl<'a, D: Domain> From<Vec<Shell<'a, D>>> for Shell<'a, D> {
fn from(vs: Vec<Shell<'a, D>>) -> Self {
vs.iter().map(|v| v.wrap()).collect::<Vec<_>>().into()
}
}
impl<'a, D: Domain> From<Set<ShellHandle<'a, D>>> for Shell<'a, D> {
fn from(vs: Set<ShellHandle<'a, D>>) -> Self {
Shell::Set(vs)
}
}
impl<'a, D: Domain> From<Map<ShellHandle<'a, D>, ShellHandle<'a, D>>> for Shell<'a, D> {
fn from(vs: Map<ShellHandle<'a, D>, ShellHandle<'a, D>>) -> Self {
Shell::Dictionary(vs)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Record<V>(Vec<V> /* at least one element, for the label */);
impl<V> Record<V> {
pub fn new(label: V, mut fields: Vec<V>) -> Self {
fields.insert(0, label);
Record(fields)
}
pub fn _from_vec(v: Vec<V>) -> Self {
if v.is_empty() { panic!("Internal error: empty vec supplied to Record::_from_vec") }
Record(v)
}
pub fn _vec(&self) -> &Vec<V> {
&self.0
}
}
#[derive(Clone)]
pub struct Annotations<V: ValueImpl>(Box<(V::Handle, Vec<<V::IOValueImpl as ValueImpl>::Handle>)>);
impl<V: ValueImpl> Annotations<V> {
pub fn new(v: V::Handle, anns: Vec<<V::IOValueImpl as ValueImpl>::Handle>) -> Self {
Self(Box::new((v, anns)))
}
}
impl<V: ValueImpl> Hash for Annotations<V> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.as_ref().0.hash(state)
}
}
impl<V: ValueImpl> PartialEq for Annotations<V> {
fn eq(&self, other: &Self) -> bool {
self.0.as_ref().0.eq(&other.0.as_ref().0)
}
}
impl<V: ValueImpl> Ord for Annotations<V> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.as_ref().0.cmp(&other.0.as_ref().0)
}
}
impl<V: ValueImpl> Eq for Annotations<V> {}
impl<V: ValueImpl> PartialOrd for Annotations<V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub fn copy_iovalue<V: ValueImpl<Embedded = <V as ValueImpl>::Handle>>(v: &V::Handle) -> IOValue {
IOValue::copy::<V, _, _>(v, &mut |a| Result::<_, ()>::Ok(copy_iovalue::<V>(a))).unwrap()
}
pub type IOValueImpl = Shell<'static, IOValue>;
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct IOValue(ShellHandle<'static, IOValue>);
unsafe impl TransparentWrapper<ShellHandle<'static, IOValue>> for IOValue {}
impl Domain for IOValue {
type Decode = IOValueDomainCodec;
type Encode = IOValueDomainCodec;
}
impl Debug for IOValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
IOValue::peel_ref(self).fmt(f)
}
}
impl IOValue {
pub fn value(&self) -> &IOValueImpl {
self.0.as_ref()
}
}
impl<T: Into<IOValueImpl>> From<T> for IOValue {
fn from(t: T) -> Self {
IOValue(t.into().wrap())
}
}
impl Borrow<IOValueImpl> for IOValue {
fn borrow(&self) -> &IOValueImpl {
self.0.as_ref()
}
}
impl FromStr for IOValue {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
crate::annotated_iovalue_from_str(s)
}
}
impl From<<IOValueImpl as ValueImpl>::Handle> for IOValue {
fn from(h: <IOValueImpl as ValueImpl>::Handle) -> Self {
TransparentWrapper::wrap(h)
}
}
impl<'a> From<&'a <IOValueImpl as ValueImpl>::Handle> for &'a IOValue {
fn from(h: &'a <IOValueImpl as ValueImpl>::Handle) -> Self {
TransparentWrapper::wrap_ref(h)
}
}
impl From<IOValue> for <IOValueImpl as ValueImpl>::Handle {
fn from(i: IOValue) -> Self {
IOValue::peel(i)
}
}
impl<'a> From<&'a IOValue> for &'a <IOValueImpl as ValueImpl>::Handle {
fn from(i: &'a IOValue) -> Self {
IOValue::peel_ref(i)
}
}
impl ValueImpl for IOValue {
type Handle = IOValue;
type Embedded = IOValue;
type Mapped<E: Domain> = Shell<'static, 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;
fn wrap(self) -> Self::Handle {
self
}
fn value_class(&self) -> ValueClass {
self.value().value_class()
}
fn as_boolean(&self) -> Option<bool> {
self.value().as_boolean()
}
fn as_float(&self) -> Option<f32> {
self.value().as_float()
}
fn as_double(&self) -> Option<f64> {
self.value().as_double()
}
fn as_signed_integer(&self) -> Option<Cow<'_, SignedInteger>> {
self.value().as_signed_integer()
}
fn as_string(&self) -> Option<Cow<'_, str>> {
self.value().as_string()
}
fn as_bytestring(&self) -> Option<Cow<'_, [u8]>> {
self.value().as_bytestring()
}
fn as_symbol(&self) -> Option<Cow<'_, str>> {
self.value().as_symbol()
}
fn is_record(&self) -> bool {
self.value().is_record()
}
fn label(&self) -> Self::Handle {
self.value().label().into()
}
fn is_sequence(&self) -> bool {
self.value().is_sequence()
}
fn len(&self) -> usize {
self.value().len()
}
fn index(&self, i: usize) -> Self::Handle {
self.value().index(i).into()
}
fn iter(&self) -> Self::Items<'_> {
todo!() // self.value().iter()
}
fn is_set(&self) -> bool {
self.value().is_set()
}
fn has<E: ValueImpl<Embedded = Self::Embedded>>(&self, v: &E::Handle) -> bool {
self.value().has::<E>(v)
}
fn is_dictionary(&self) -> bool {
self.value().is_dictionary()
}
fn get<K: ValueImpl<Embedded = Self::Embedded>>(&self, k: &K::Handle) -> Option<Self::Handle> {
self.value().get::<K>(k).map(|v| v.into())
}
fn entries(&self) -> Self::Entries<'_> {
todo!() // self.value().entries()
}
fn as_embedded(&self) -> Option<Cow<'_, Self::Embedded>> {
self.value().as_embedded()
}
fn annotations(&self) -> Option<Cow<'_, [IOValue]>> {
self.value().annotations()
}
fn peeled(v: &Self::Handle) -> Self::Handle {
TransparentWrapper::wrap(Shell::peeled(IOValue::peel_ref(v)))
}
fn copy<E: ValueImpl, F, Err>(w: &E::Handle, f: &mut F) -> Result<Self::Handle, Err>
where
F: FnMut(&E::Embedded) -> Result<Self::Handle, Err> {
IOValueImpl::copy::<E, _, _>(w, &mut |e| f(e).map(|v| v.into())).map(|v| v.into())
}
fn map_embedded<E: Domain, F, Err>(v: &Self::Handle, f: &mut F) -> Result<<Self::Mapped<E> as ValueImpl>::Handle, Err>
where
F: FnMut(&Self::Embedded) -> Result<E, Err> {
IOValueImpl::map_embedded(v.into(), f)
}
}

View File

@ -1,4 +1,5 @@
use num_bigint::BigInt;
use std::borrow::Borrow;
use std::io;
use crate::AtomClass;
@ -85,7 +86,7 @@ pub fn write_value<V: ValueImpl>(
for ann in &anns[..] {
annotation_b.shift(Some(B::Item::Annotation));
w.boundary(&annotation_b)?;
ann.write(w, &mut IOValueDomainCodec)?;
ann.borrow().write(w, &mut IOValueDomainCodec)?;
}
annotation_b.shift(Some(B::Item::AnnotatedValue));
w.boundary(&annotation_b)?;
@ -110,11 +111,11 @@ pub fn write_value<V: ValueImpl>(
w.start_record()?;
let mut b = B::start(B::Item::RecordLabel);
w.boundary(&b)?;
v.label().write(w, enc)?;
v.label().borrow().write(w, enc)?;
for e in v.iter() {
b.shift(Some(B::Item::RecordField));
w.boundary(&b)?;
e.write(w, enc)?;
e.borrow().write(w, enc)?;
}
b.shift(None);
w.boundary(&b)?;
@ -126,7 +127,7 @@ pub fn write_value<V: ValueImpl>(
for e in v.iter() {
b.shift(Some(B::Item::SequenceValue));
w.boundary(&b)?;
e.write(w, enc)?;
e.borrow().write(w, enc)?;
}
b.shift(None);
w.boundary(&b)?;
@ -138,7 +139,7 @@ pub fn write_value<V: ValueImpl>(
for e in v.iter() {
b.shift(Some(B::Item::SetValue));
w.boundary(&b)?;
e.write(w, enc)?;
e.borrow().write(w, enc)?;
}
b.shift(None);
w.boundary(&b)?;
@ -150,10 +151,10 @@ pub fn write_value<V: ValueImpl>(
for (k, v) in v.entries() {
b.shift(Some(B::Item::DictionaryKey));
w.boundary(&b)?;
k.write(w, enc)?;
k.borrow().write(w, enc)?;
b.shift(Some(B::Item::DictionaryValue));
w.boundary(&b)?;
v.write(w, enc)?;
v.borrow().write(w, enc)?;
}
b.shift(None);
w.boundary(&b)?;
@ -162,7 +163,7 @@ pub fn write_value<V: ValueImpl>(
}
ValueClass::Embedded => {
w.start_embedded()?;
enc.encode_embedded(w, &v.embedded())?;
enc.encode_embedded(w, &v.as_embedded().unwrap())?;
w.end_embedded()?
}
}