preserves 5.0.0-rc.9

Implementation of the Preserves serialization format.
Documentation
use std::borrow::Borrow;
use std::borrow::Cow;
use std::fmt::Debug;
use std::io;
use std::str::FromStr;

use bytemuck::TransparentWrapper;

use crate::Atom;
use crate::Bytes;
use crate::Domain;
use crate::DomainDecode;
use crate::DomainEncode;
use crate::Embedded;
use crate::Error;
use crate::Map;
use crate::Record;
use crate::Set;
use crate::SignedInteger;
use crate::Symbol;
use crate::Value;
use crate::ValueClass;
use crate::ValueImpl;
use crate::Writer;
use crate::reader::ReaderResult;
use crate::read_iovalue_text;

#[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[repr(transparent)]
pub struct IOValue(pub IOValueImpl);
pub type IOValueImpl = Value<IOValue>;

#[derive(Default)] pub struct IOValueDomainDecode;
#[derive(Default)] pub struct IOValueDomainEncode;

unsafe impl TransparentWrapper<IOValueImpl> for IOValue {}

impl Domain for IOValue {}

impl Debug for IOValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        crate::TextWriter::fmt_value(f, &mut IOValueDomainEncode, self)
            .map_err(|_| std::fmt::Error)
    }
}

impl IOValue {
    pub fn new<V: ValueImpl<IOValue> + Sync + Send + 'static>(v: V) -> IOValue {
        IOValue(Value::new(v))
    }

    pub fn record(label: IOValue, fields: Vec<IOValue>) -> Self {
        Self::new(Record::new(Value::<IOValue>::from(label),
                              fields.into_iter().map(|f| f.into()).collect()))
    }

    pub fn symbol<T: AsRef<str> + Clone + std::fmt::Debug + Sync + Send + 'static>(t: T) -> Self {
        Self::new(Symbol::new(t))
    }

    pub fn bytes<T: AsRef<[u8]> + Clone + Debug + Sync + Send + 'static>(t: T) -> Self {
        Self::new(Bytes::new(t))
    }

    pub fn embedded(d: IOValue) -> Self {
        Self::new(Embedded::new(d))
    }

    pub fn value(&self) -> &IOValueImpl {
        &self.0
    }
}

impl AsRef<IOValue> for IOValueImpl {
    fn as_ref(&self) -> &IOValue {
        self.into()
    }
}

impl AsRef<IOValueImpl> for IOValue {
    fn as_ref(&self) -> &IOValueImpl {
        self.into()
    }
}

impl Borrow<IOValueImpl> for IOValue {
    fn borrow(&self) -> &IOValueImpl {
        &self.0
    }
}

impl std::ops::Deref for IOValue {
    type Target = IOValueImpl;

    fn deref(&self) -> &Self::Target {
        self.into()
    }
}

impl FromStr for IOValue {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        read_iovalue_text(s, true)
    }
}

impl From<IOValueImpl> for IOValue {
    fn from(h: IOValueImpl) -> Self {
        TransparentWrapper::wrap(h)
    }
}

impl<'r> From<&'r IOValueImpl> for &'r IOValue {
    fn from(h: &'r IOValueImpl) -> Self {
        TransparentWrapper::wrap_ref(h)
    }
}

impl From<IOValue> for IOValueImpl {
    fn from(i: IOValue) -> Self {
        IOValue::peel(i)
    }
}

impl<'r> From<&'r IOValue> for &'r IOValueImpl {
    fn from(i: &'r IOValue) -> Self {
        IOValue::peel_ref(i)
    }
}

impl ValueImpl<IOValue> for IOValue {
    fn write(&self, w: &mut dyn Writer, enc: &mut dyn DomainEncode<IOValue>) -> io::Result<()> {
        self.0.write(w, enc)
    }

    fn owned_value(&self) -> Value<IOValue> {
        IOValue::peel_ref(self).clone()
    }

    fn value_class(&self) -> ValueClass {
        self.value().value_class()
    }

    fn as_atom(&self) -> Option<Atom<'_>> {
        self.value().as_atom()
    }

    fn as_boolean(&self) -> Option<bool> {
        self.value().as_boolean()
    }

    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) -> Value<IOValue> {
        self.value().label().into()
    }

    fn collect_record(&self) -> Option<Cow<'_, Record<Value<IOValue>>>> {
        self.value().collect_record()
    }

    fn collect_simple_record(&self, name: &str, arity: Option<usize>) -> Option<Cow<'_, Record<Value<IOValue>>>> {
        self.value().collect_simple_record(name, arity)
    }

    fn is_sequence(&self) -> bool {
        self.value().is_sequence()
    }

    fn len(&self) -> usize {
        self.value().len()
    }

    fn index(&self, i: usize) -> Value<IOValue> {
        self.value().index(i).into()
    }

    fn iter(&self) -> Box<dyn Iterator<Item = Value<IOValue>> + '_> {
        self.value().iter()
    }

    fn collect_sequence(&self) -> Option<Cow<'_, Vec<Value<IOValue>>>> {
        self.value().collect_sequence()
    }

    fn is_set(&self) -> bool {
        self.value().is_set()
    }

    fn has(&self, v: &Value<IOValue>) -> bool {
        self.value().has(v)
    }

    fn collect_set(&self) -> Option<Cow<'_, Set<Value<IOValue>>>> {
        self.value().collect_set()
    }

    fn is_dictionary(&self) -> bool {
        self.value().is_dictionary()
    }

    fn get(&self, k: &Value<IOValue>) -> Option<Value<IOValue>> {
        self.value().get(k)
    }

    fn entries(&self) -> Box<dyn Iterator<Item = (Value<IOValue>, Value<IOValue>)> + '_> {
        self.value().entries()
    }

    fn keys(&self) -> Box<dyn Iterator<Item = Value<IOValue>> + '_> {
        self.value().keys()
    }

    fn collect_dictionary(&self) -> Option<Cow<'_, Map<Value<IOValue>, Value<IOValue>>>> {
        self.value().collect_dictionary()
    }

    fn as_embedded(&self) -> Option<Cow<'_, IOValue>> {
        self.value().as_embedded()
    }

    fn annotations(&self) -> Option<Cow<'_, [IOValue]>> {
        self.value().annotations()
    }

    fn inner_peeled(&self) -> Option<Value<IOValue>> {
        self.value().inner_peeled()
    }
}

impl DomainDecode<IOValue> for IOValueDomainDecode {
    fn decode_value(&mut self, v: IOValue) -> ReaderResult<IOValue> {
        Ok(v)
    }
}

impl DomainEncode<IOValue> for IOValueDomainEncode {
    fn encode_value(&mut self, d: &IOValue) -> io::Result<IOValue> {
        Ok(d.clone())
    }
}