preserves/implementations/rust/preserves/src/shell.rs

901 lines
31 KiB
Rust

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::BinarySource;
use crate::BytesBinarySource;
use crate::CompoundClass;
use crate::DefaultDomainCodec;
use crate::Domain;
use crate::DomainDecode;
use crate::DomainEncode;
use crate::Error;
use crate::ExpectedKind;
use crate::IOValueDomainDecode;
use crate::IOValueDomainEncode;
use crate::Reader;
use crate::SignedInteger;
use crate::ValueClass;
use crate::ValueImpl;
use crate::ValueReader;
use crate::Writer;
use crate::boundary as B;
use crate::error::ReadError;
use crate::error::io_eof;
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 into_owned(self) -> Atom<'static> {
match self {
Atom::Boolean(b) => Atom::Boolean(b),
Atom::Float(f) => Atom::Float(f),
Atom::Double(d) => Atom::Double(d),
Atom::SignedInteger(i) => Atom::SignedInteger(i.to_owned()),
Atom::String(s) => Atom::String(s.to_owned()),
Atom::ByteString(bs) => Atom::ByteString(bs.to_owned()),
Atom::Symbol(s) => Atom::Symbol(s.to_owned()),
}
}
pub fn write(&self, w: &mut dyn Writer) -> io::Result<()> {
match self {
Atom::Boolean(b) => w.write_bool(*b),
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)) } }
impl<'a> From<i8> for Atom<'a> { fn from(i: i8) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<u8> for Atom<'a> { fn from(i: u8) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<i16> for Atom<'a> { fn from(i: i16) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<u16> for Atom<'a> { fn from(i: u16) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<i32> for Atom<'a> { fn from(i: i32) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<u32> for Atom<'a> { fn from(i: u32) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<i64> for Atom<'a> { fn from(i: i64) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<u64> for Atom<'a> { fn from(i: u64) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<i128> for Atom<'a> { fn from(i: i128) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<u128> for Atom<'a> { fn from(i: u128) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<isize> for Atom<'a> { fn from(i: isize) -> Self { SignedInteger::from(i).into() } }
impl<'a> From<usize> for Atom<'a> { fn from(i: usize) -> Self { SignedInteger::from(i).into() } }
macro_rules! from_atom_ref_impl {
($t:ty, $p:pat, $e:expr, $errty:ty, $err:expr) => {
impl<'r, 'a> TryFrom<&'r Atom<'a>> for $t {
type Error = $errty;
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, ExpectedKind::Boolean);
from_atom_ref_impl!(f32, Atom::Float(f), *f, ExpectedKind, ExpectedKind::Float);
from_atom_ref_impl!(f64, Atom::Double(d), *d, ExpectedKind, ExpectedKind::Double);
from_atom_ref_impl!(&'a SignedInteger, Atom::SignedInteger(i), i.as_ref(), ExpectedKind, ExpectedKind::SignedInteger);
from_atom_ref_impl!(&'a str, Atom::String(s), s.as_ref(), ExpectedKind, ExpectedKind::String);
from_atom_ref_impl!(&'a [u8], Atom::ByteString(bs), bs.as_ref(), ExpectedKind, ExpectedKind::ByteString);
from_atom_ref_impl!(i8, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(u8, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(i16, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(u16, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(i32, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(u32, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(i64, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(u64, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(i128, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(u128, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(isize, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
from_atom_ref_impl!(usize, Atom::SignedInteger(i), i.as_ref().try_into()?, Error, Error::Expected(ExpectedKind::SignedInteger));
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<'de, D: Domain<'de>> {
Atom(Atom<'de>),
Record(Record<ShellHandle<'de, D>>),
Sequence(Vec<ShellHandle<'de, D>>),
Set(Set<ShellHandle<'de, D>>),
Dictionary(Map<ShellHandle<'de, D>, ShellHandle<'de, D>>),
Embedded(D),
Annotated(Annotations<'de, Self>),
}
impl<'de, D: Domain<'de>> Shell<'de, D> {
pub fn record(label: ShellHandle<'de, D>, fields: Vec<ShellHandle<'de, D>>) -> Self {
Shell::Record(Record::new(label, fields))
}
pub fn symbol<S: Into<Cow<'de, str>>>(s: S) -> Self {
Shell::Atom(Atom::symbol(s))
}
pub fn embedded(d: D) -> Self {
Shell::Embedded(d)
}
}
impl<'de, D: Domain<'de>> ValueReader<'de> for Shell<'de, D> {
type Impl = Shell<'de, D>;
fn read_impl<R: Reader<'de> + ?Sized, Dec: DomainDecode<'de, <Self::Impl as ValueImpl<'de>>::Embedded>>(
r: &mut R,
read_annotations: bool,
dec: &mut Dec,
) -> Result<Self::Impl, ReadError> {
Ok(read(r, read_annotations, dec)?)
}
fn read_iovalue<R: Reader<'de> + ?Sized>(
r: &mut R,
read_annotations: bool,
) -> Result<<Self::Impl as ValueImpl<'de>>::IOEmbedded, ReadError> {
Ok(Shell::<'de, IOValue>::read_impl(
r,
read_annotations,
&mut IOValueDomainDecode::<Shell<'de, IOValue>>::default())?.into())
}
}
impl<'de, Err: Into<io::Error>, D: Domain<'de> + FromStr<Err = Err>> FromStr for Shell<'de, D> {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(Shell::read_impl(&mut BytesBinarySource::new(s.as_bytes()).text(), true, &mut DefaultDomainCodec)?)
}
}
impl<'de, D: Domain<'de>> ValueImpl<'de> for Shell<'de, D> {
type Handle = ShellHandle<'de, D>;
type Embedded = D;
type Mapped<E: Domain<'de>> = Shell<'de, 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 IOEmbedded = IOValue<'de>;
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.write(w, &mut IOValueDomainEncode::<Self>::default())?;
}
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<'de>, 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>).map(|a| a.into()).collect()
)))).wrap())
} else {
Ok(r)
}
}
fn map_embedded<E: Domain<'de>, F, Err>(v: &Self::Handle, f: &mut F) -> Result<<Self::Mapped<E> as ValueImpl<'de>>::Handle, Err>
where
F: FnMut(&D) -> Result<E, Err>
{
Self::Mapped::<E>::copy::<Self, _, _>(v, &mut |d| Ok(
ShellHandle::<'de, 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<'de, 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<'de, 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::Mapped<Self::IOEmbedded> as ValueImpl<'de>>::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!({'de, D: Domain<'de>}, Shell<'de, D>);
impl<'de, W: Into<Atom<'de>>, D: Domain<'de>> From<W> for Shell<'de, D> {
fn from(w: W) -> Self {
Shell::Atom(w.into())
}
}
impl<'de, D: Domain<'de>> From<Vec<ShellHandle<'de, D>>> for Shell<'de, D> {
fn from(vs: Vec<ShellHandle<'de, D>>) -> Self {
Shell::Sequence(vs)
}
}
impl<'de, D: Domain<'de>> From<Vec<Shell<'de, D>>> for Shell<'de, D> {
fn from(vs: Vec<Shell<'de, D>>) -> Self {
vs.iter().map(|v| v.wrap()).collect::<Vec<_>>().into()
}
}
impl<'de, D: Domain<'de>> From<Set<ShellHandle<'de, D>>> for Shell<'de, D> {
fn from(vs: Set<ShellHandle<'de, D>>) -> Self {
Shell::Set(vs)
}
}
impl<'de, D: Domain<'de>> From<Map<ShellHandle<'de, D>, ShellHandle<'de, D>>> for Shell<'de, D> {
fn from(vs: Map<ShellHandle<'de, D>, ShellHandle<'de, 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<'de, V: ValueImpl<'de>>(Box<(V::Handle, Vec<<V::Mapped<V::IOEmbedded> as ValueImpl<'de>>::Handle>)>);
impl<'de, V: ValueImpl<'de>> Annotations<'de, V> {
pub fn new(v: V::Handle, anns: Vec<<V::Mapped<V::IOEmbedded> as ValueImpl<'de>>::Handle>) -> Self {
Self(Box::new((v, anns)))
}
}
impl<'de, V: ValueImpl<'de>> Hash for Annotations<'de, V> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.0.as_ref().0.hash(state)
}
}
impl<'de, V: ValueImpl<'de>> PartialEq for Annotations<'de, V> {
fn eq(&self, other: &Self) -> bool {
self.0.as_ref().0.eq(&other.0.as_ref().0)
}
}
impl<'de, V: ValueImpl<'de>> Ord for Annotations<'de, V> {
fn cmp(&self, other: &Self) -> Ordering {
self.0.as_ref().0.cmp(&other.0.as_ref().0)
}
}
impl<'de, V: ValueImpl<'de>> Eq for Annotations<'de, V> {}
impl<'de, V: ValueImpl<'de>> PartialOrd for Annotations<'de, V> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub fn copy_iovalue<'de, V: ValueImpl<'de>>(v: &<V::Mapped<V::IOEmbedded> as ValueImpl<'de>>::Handle) -> IOValue<'de> {
Shell::copy::<V::Mapped<V::IOEmbedded>, _, _>(v, &mut |a| Result::<_, ()>::Ok(
copy_iovalue::<V>(a.as_ref()).into())).unwrap().into()
}
pub type IOValueImpl<'a> = Shell<'a, IOValue<'a>>;
pub type IOValueIso<'a> = ShellHandle<'a, IOValue<'a>>;
#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct IOValue<'a>(IOValueIso<'a>);
unsafe impl<'a> TransparentWrapper<IOValueIso<'a>> for IOValue<'a> {}
impl<'de> Domain<'de> for IOValue<'de> {
type Decode = IOValueDomainDecode<'de, IOValueImpl<'de>>;
type Encode = IOValueDomainEncode<'de, Self>;
}
impl<'de> Debug for IOValue<'de> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
IOValue::peel_ref(self).fmt(f)
}
}
impl<'de> IOValue<'de> {
pub fn record(label: IOValue<'de>, fields: Vec<IOValue<'de>>) -> Self {
IOValue(Shell::Record(Record::new(
label.into(),
fields.into_iter().map(|f| f.into()).collect())).wrap())
}
pub fn value(&self) -> &IOValueImpl<'de> {
self.0.as_ref()
}
pub fn iso(self) -> IOValueIso<'de> {
IOValue::peel(self)
}
}
pub fn iso_parse<'a>(s: &'a str) -> io::Result<IOValueIso<'a>> {
Ok(IOValue::from_str(s)?.iso())
}
impl<'de, T: Into<IOValueImpl<'de>>> From<T> for IOValue<'de> {
fn from(t: T) -> Self {
IOValue(t.into().wrap())
}
}
impl<'de> Borrow<IOValueImpl<'de>> for IOValue<'de> {
fn borrow(&self) -> &IOValueImpl<'de> {
self.0.as_ref()
}
}
impl<'de> AsRef<Arc<Shell<'de, IOValue<'de>>>> for IOValue<'de> {
fn as_ref(&self) -> &Arc<Shell<'de, IOValue<'de>>> {
&self.0
}
}
impl<'de> FromStr for IOValue<'de> {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
crate::annotated_iovalue_from_str(s)
}
}
impl<'de> From<<IOValueImpl<'de> as ValueImpl<'de>>::Handle> for IOValue<'de> {
fn from(h: <IOValueImpl<'de> as ValueImpl<'de>>::Handle) -> Self {
TransparentWrapper::wrap(h)
}
}
impl<'r, 'de> From<&'r <IOValueImpl<'de> as ValueImpl<'de>>::Handle> for &'r IOValue<'de> {
fn from(h: &'r <IOValueImpl<'de> as ValueImpl<'de>>::Handle) -> Self {
TransparentWrapper::wrap_ref(h)
}
}
impl<'de> From<IOValue<'de>> for <IOValueImpl<'de> as ValueImpl<'de>>::Handle {
fn from(i: IOValue<'de>) -> Self {
IOValue::peel(i)
}
}
impl<'r, 'de> From<&'r IOValue<'de>> for &'r <IOValueImpl<'de> as ValueImpl<'de>>::Handle {
fn from(i: &'r IOValue<'de>) -> Self {
IOValue::peel_ref(i)
}
}
impl<'de> ValueReader<'de> for IOValue<'de> {
type Impl = Self;
fn read_impl<R: Reader<'de> + ?Sized, Dec: DomainDecode<'de, <Self::Impl as ValueImpl<'de>>::Embedded>>(
r: &mut R,
read_annotations: bool,
dec: &mut Dec,
) -> Result<Self::Impl, ReadError> {
Ok(read(r, read_annotations, dec)?.into())
}
fn read_iovalue<R: Reader<'de> + ?Sized>(
r: &mut R,
read_annotations: bool,
) -> Result<<Self::Impl as ValueImpl<'de>>::IOEmbedded, ReadError> {
Self::read_domain(r, read_annotations, &mut IOValueDomainDecode::<Self>::default())
}
}
impl<'de> ValueImpl<'de> for IOValue<'de> {
type Handle = Self;
type Embedded = Self;
type Mapped<E: Domain<'de>> = Shell<'de, 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 IOEmbedded = Self;
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<'de, 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<'de, 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<'_, [<Self::Mapped<Self::IOEmbedded> as ValueImpl<'de>>::Handle]>> {
self.value().annotations()
}
fn peeled(v: &Self::Handle) -> Self::Handle {
TransparentWrapper::wrap(Shell::peeled(IOValue::peel_ref(v)))
}
fn copy<E: ValueImpl<'de>, 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<'de>, F, Err>(v: &Self::Handle, f: &mut F) -> Result<<Self::Mapped<E> as ValueImpl<'de>>::Handle, Err>
where
F: FnMut(&Self::Embedded) -> Result<E, Err> {
IOValueImpl::map_embedded(v.into(), f)
}
}
pub fn read<'de, R: Reader<'de> + ?Sized, D: Domain<'de>, Dec: DomainDecode<'de, D>>(
r: &mut R,
read_annotations: bool,
dec: &mut Dec,
) -> io::Result<Shell<'de, D>> {
let (anns, v) = match read_annotations {
true => IOValue::gather_annotations(r)?.ok_or_else(io_eof)?,
false => (Vec::new(), r.skip_annotations()?.ok_or_else(io_eof)?),
};
let value = match v {
ValueClass::Atomic(_) =>
Shell::Atom(r.next_atom()?),
ValueClass::Embedded => {
r.open_embedded()?;
let v = dec.decode_embedded(r, read_annotations)?;
r.close_embedded()?;
Shell::Embedded(v)
}
ValueClass::Compound(CompoundClass::Record) => {
let mut vs = Vec::new();
r.open_record()?;
let mut b = B::start(B::Item::RecordLabel);
r.boundary(&b)?;
vs.push(read(r, read_annotations, dec)?.wrap());
while !r.close_compound(&mut b, &B::Item::RecordField)? {
vs.push(read(r, read_annotations, dec)?.wrap());
}
Shell::Record(Record::_from_vec(vs))
}
ValueClass::Compound(CompoundClass::Sequence) => {
let mut vs = Vec::new();
r.open_sequence()?;
let mut b = B::Type::default();
while !r.close_compound(&mut b, &B::Item::SequenceValue)? {
vs.push(read(r, read_annotations, dec)?.wrap());
}
Shell::Sequence(vs)
}
ValueClass::Compound(CompoundClass::Set) => {
let mut s = Set::new();
r.open_set()?;
let mut b = B::Type::default();
while !r.close_compound(&mut b, &B::Item::SetValue)? {
s.insert(read(r, read_annotations, dec)?.wrap());
}
Shell::Set(s)
}
ValueClass::Compound(CompoundClass::Dictionary) => {
let mut d = Map::new();
r.open_dictionary()?;
let mut b = B::Type::default();
while !r.close_compound(&mut b, &B::Item::DictionaryKey)? {
let k = read(r, read_annotations, dec)?.wrap();
b.shift(Some(B::Item::DictionaryValue));
r.boundary(&b)?;
d.insert(k, read(r, read_annotations, dec)?.wrap());
}
Shell::Dictionary(d)
}
};
if anns.is_empty() {
Ok(value)
} else {
Ok(Shell::Annotated(Annotations::new(value.wrap(), anns)))
}
}