More WIP; Handles
This commit is contained in:
parent
eeb50fcf65
commit
4070c5252d
|
@ -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)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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()?
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue