preserves 5.0.0-rc.9

Implementation of the Preserves serialization format.
Documentation
use std::borrow::Cow;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::io;
use std::marker::PhantomData;

use crate::Atom;
use crate::BinarySource;
use crate::BytesBinarySource;
use crate::CompoundClass;
use crate::Domain;
use crate::DomainDecode;
use crate::IOValue;
use crate::SignedInteger;
use crate::Value;
use crate::ValueClass;
use crate::boundary as B;
use crate::error::Error;
use crate::error::SyntaxError;
use crate::error::ExpectedKind;
use crate::error::UnexpectedKind;
use crate::signed_integer::OutOfRange;

pub type ReaderResult<T> = std::result::Result<T, Error>;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NextToken {
    Annotation,
    Value(ValueClass),
    End,
}

pub enum FullToken<'de> {
    Embedded,
    Atom(Atom<'de>),
    Compound(CompoundClass),
    End,
}

pub trait ValueReader<D: Domain> {
    fn read<'de, R: Reader<'de> + ?Sized, Dec: DomainDecode<D>>(
        r: &mut R,
        read_annotations: bool,
        dec: &mut Dec,
    ) -> ReaderResult<Value<D>>;

    //---------------------------------------------------------------------------

    fn read_text<Dec: DomainDecode<D>>(
        s: &str,
        read_annotations: bool,
        dec: &mut Dec,
    ) -> ReaderResult<Value<D>> {
        Ok(Self::read(&mut BytesBinarySource::new(s.as_bytes()).text(), read_annotations, dec)?)
    }

    fn read_packed<Dec: DomainDecode<D>>(
        bs: &[u8],
        read_annotations: bool,
        dec: &mut Dec,
    ) -> ReaderResult<Value<D>> {
        Ok(Self::read(&mut BytesBinarySource::new(bs).packed(), read_annotations, dec)?)
    }
}

pub trait IOValueReader: ValueReader<IOValue> {
    fn read_iovalue<'de, R: Reader<'de> + ?Sized>(
        r: &mut R,
        read_annotations: bool,
    ) -> ReaderResult<IOValue>;

    fn read_iovalue_text(s: &str, read_annotations: bool) -> ReaderResult<IOValue> {
        Ok(Self::read_iovalue(&mut BytesBinarySource::new(s.as_bytes()).text(), read_annotations)?)
    }

    fn read_iovalue_packed(bs: &[u8], read_annotations: bool) -> ReaderResult<IOValue> {
        Ok(Self::read_iovalue(&mut BytesBinarySource::new(bs).packed(), read_annotations)?)
    }

    fn gather_annotations<'de, R: Reader<'de> + ?Sized>(
        r: &mut R,
    ) -> ReaderResult<Option<(Vec<IOValue>, ValueClass)>> {
        let mut anns = Vec::new();
        loop {
            match r.peek_class()? {
                Some(NextToken::Annotation) => {
                    r.open_annotation()?;
                    anns.push(Self::read_iovalue(r, true)?);
                    r.close_annotation()?;
                }
                Some(NextToken::Value(v)) => return Ok(Some((anns, v))),
                Some(NextToken::End) => return Err(r.wrap_syntax_error(
                    SyntaxError::Unexpected(UnexpectedKind::CloseDelimiter))),
                None => return Ok(None),
            }
        }
    }
}

pub trait Reader<'de> {
    type ValueReader<D: Domain>: ValueReader<D>;
    type IOValueReader: IOValueReader;

    fn peek_class(&mut self) -> ReaderResult<Option<NextToken>>;

    fn skip_atom(&mut self) -> ReaderResult<()>;
    fn next_atom(&mut self) -> ReaderResult<Atom<'de>>;

    fn boundary(&mut self, b: &B::Type) -> ReaderResult<()>;

    fn open_record(&mut self) -> ReaderResult<()>;
    fn open_sequence(&mut self) -> ReaderResult<()>;
    fn open_set(&mut self) -> ReaderResult<()>;
    fn open_dictionary(&mut self) -> ReaderResult<()>;

    // Answers true for closed, false for more.
    // Implies a b.shift of None if closed or of Some(i) if not closed, plus a .boundary.
    fn close_compound(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<bool>;

    fn open_embedded(&mut self) -> ReaderResult<()>;
    fn close_embedded(&mut self) -> ReaderResult<()>;

    fn open_annotation(&mut self) -> ReaderResult<()>;
    fn close_annotation(&mut self) -> ReaderResult<()>;

    fn mark(&mut self) -> io::Result<usize>;
    fn restore(&mut self, mark: usize) -> io::Result<()>;

    fn wrap_syntax_error(&mut self, e: SyntaxError) -> Error;

    //---------------------------------------------------------------------------

    fn has_next(&mut self) -> ReaderResult<bool> {
        Ok(self.peek_class()?.is_some())
    }

    fn next<D: Domain, Dec: DomainDecode<D>>(
        &mut self,
        read_annotations: bool,
        dec: &mut Dec,
    ) -> ReaderResult<Value<D>> {
        Self::ValueReader::read(self, read_annotations, dec)
    }

    fn next_iovalue(&mut self, read_annotations: bool) -> ReaderResult<IOValue> {
        Self::IOValueReader::read_iovalue(self, read_annotations)
    }

    fn try_next<D: Domain, Dec: DomainDecode<D>>(
        &mut self,
        read_annotations: bool,
        dec: &mut Dec,
    ) -> ReaderResult<Option<Value<D>>> {
        Ok(self.has_next()?.then(
            || Self::ValueReader::read(self, read_annotations, dec)).transpose()?)
    }

    fn try_next_iovalue(&mut self, read_annotations: bool) -> ReaderResult<Option<IOValue>> {
        Ok(self.has_next()?.then(
            || Self::IOValueReader::read_iovalue(self, read_annotations)).transpose()?)
    }

    fn read_all<D: Domain, Dec: DomainDecode<D>>(
        &mut self,
        read_annotations: bool,
        dec: &mut Dec,
    ) -> ReaderResult<Vec<Value<D>>> {
        let mut vs = Vec::new();
        while self.has_next()? { vs.push(self.next(read_annotations, dec)?); }
        Ok(vs)
    }

    fn read_all_iovalues(
        &mut self,
        read_annotations: bool,
    ) -> ReaderResult<Vec<IOValue>> {
        let mut vs = Vec::new();
        while self.has_next()? { vs.push(self.next_iovalue(read_annotations)?); }
        Ok(vs)
    }

    fn next_full_token(&mut self) -> ReaderResult<FullToken<'de>> {
        match self.skip_annotations() {
            Ok(Some(ValueClass::Atomic(_))) => Ok(FullToken::Atom(self.next_atom()?)),
            Ok(Some(ValueClass::Compound(c))) => Ok(FullToken::Compound(c)),
            Ok(Some(ValueClass::Embedded)) => Ok(FullToken::Embedded),
            Ok(None) => Err(self.wrap_syntax_error(SyntaxError::eof())),
            Err(Error::SyntaxError { detail: SyntaxError::Unexpected(UnexpectedKind::CloseDelimiter), .. }) =>
                Ok(FullToken::End),
            Err(e) => Err(e),
        }
    }

    fn skip_annotations(&mut self) -> ReaderResult<Option<ValueClass>> {
        loop {
            match self.peek_class()? {
                Some(NextToken::Annotation) => {
                    self.open_annotation()?;
                    self.skip_value()?;
                    self.close_annotation()?;
                }
                Some(NextToken::Value(v)) => return Ok(Some(v)),
                Some(NextToken::End) => return Err(self.wrap_syntax_error(
                    SyntaxError::Unexpected(UnexpectedKind::CloseDelimiter))),
                None => return Ok(None),
            }
        }
    }

    fn skip_value(&mut self) -> ReaderResult<()> {
        // TODO efficient skipping in specific impls of this trait
        match self.skip_annotations()?.ok_or_else(|| self.wrap_syntax_error(SyntaxError::eof()))? {
            ValueClass::Atomic(_) => self.skip_atom(),
            ValueClass::Embedded => {
                self.open_embedded()?;
                self.skip_value()?;
                self.close_embedded()?;
                Ok(())
            }
            ValueClass::Compound(CompoundClass::Record) => {
                self.open_record()?;
                let b = B::start(B::Item::RecordLabel);
                self.boundary(&b)?;
                self.skip_value()?;
                self.discard_until_complete(b, &B::Item::RecordField)
            }
            ValueClass::Compound(CompoundClass::Sequence) => {
                self.open_sequence()?;
                self.discard_until_complete(B::Type::default(), &B::Item::SequenceValue)
            }
            ValueClass::Compound(CompoundClass::Set) => {
                self.open_set()?;
                self.discard_until_complete(B::Type::default(), &B::Item::SetValue)
            }
            ValueClass::Compound(CompoundClass::Dictionary) => {
                self.open_dictionary()?;
                let mut b = B::Type::default();
                while !self.close_compound(&mut b, &B::Item::DictionaryKey)? {
                    self.skip_value()?;
                    b.shift(Some(B::Item::DictionaryValue));
                    self.boundary(&b)?;
                    self.skip_value()?;
                }
                Ok(())
            }
        }
    }

    fn next_boolean(&mut self) -> ReaderResult<bool> { next_atom_expect(self) }
    fn next_double(&mut self) -> ReaderResult<f64> { next_atom_expect(self) }
    fn next_signedinteger(&mut self) -> ReaderResult<Cow<'de, SignedInteger>> { next_atom_expect(self) }
    fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> { next_atom_expect(self) }
    fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> { next_atom_expect(self) }
    fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> {
        match self.next_atom()? {
            Atom::Symbol(s) => Ok(s),
            _ => Err(self.wrap_syntax_error(SyntaxError::Expected(ExpectedKind::Symbol))),
        }
    }

    fn next_i8(&mut self) -> ReaderResult<i8> { check_out_of_range(self) }
    fn next_u8(&mut self) -> ReaderResult<u8> { check_out_of_range(self) }
    fn next_i16(&mut self) -> ReaderResult<i16> { check_out_of_range(self) }
    fn next_u16(&mut self) -> ReaderResult<u16> { check_out_of_range(self) }
    fn next_i32(&mut self) -> ReaderResult<i32> { check_out_of_range(self) }
    fn next_u32(&mut self) -> ReaderResult<u32> { check_out_of_range(self) }
    fn next_i64(&mut self) -> ReaderResult<i64> { check_out_of_range(self) }
    fn next_u64(&mut self) -> ReaderResult<u64> { check_out_of_range(self) }
    fn next_i128(&mut self) -> ReaderResult<i128> { check_out_of_range(self) }
    fn next_u128(&mut self) -> ReaderResult<u128> { check_out_of_range(self) }

    fn open_simple_record(&mut self, name: &str) -> ReaderResult<B::Type>
    {
        self.open_record()?;
        let b = B::start(B::Item::RecordLabel);
        self.boundary(&b)?;
        let label: &str = &self.next_symbol()?;
        if label == name {
            Ok(b)
        } else {
            Err(self.wrap_syntax_error(SyntaxError::Expected(ExpectedKind::SimpleRecord(name.to_owned()))))
        }
    }

    fn ensure_more_expected(&mut self, b: &mut B::Type, i: &B::Item) -> ReaderResult<()> {
        if !self.close_compound(b, i)? {
            Ok(())
        } else {
            Err(self.wrap_syntax_error(SyntaxError::Expected(ExpectedKind::Value)))
        }
    }

    fn ensure_complete(&mut self, mut b: B::Type, i: &B::Item) -> ReaderResult<()> {
        if !self.close_compound(&mut b, i)? {
            Err(self.wrap_syntax_error(SyntaxError::Expected(ExpectedKind::CloseDelimiter)))
        } else {
            Ok(())
        }
    }

    fn discard_until_complete(&mut self, mut b: B::Type, i: &B::Item) -> ReaderResult<()> {
        while !self.close_compound(&mut b, i)? {
            self.skip_value()?;
        }
        Ok(())
    }

    fn specialized(&mut self) -> Option<(&str, &mut dyn BinarySource<'de>)> { None }
}

fn next_atom_expect<'de, R: Reader<'de> + ?Sized, T: TryFrom<Atom<'de>, Error = ExpectedKind>>(r: &mut R) -> ReaderResult<T> {
    match r.next_atom()?.try_into() {
        Ok(v) => Ok(v),
        Err(k) => Err(r.wrap_syntax_error(SyntaxError::Expected(k))),
    }
}

fn check_out_of_range<'de, R: Reader<'de> + ?Sized, T: for<'i> TryFrom<&'i SignedInteger, Error = OutOfRange>>(r: &mut R) -> ReaderResult<T> {
    let i = r.next_signedinteger()?;
    Ok(T::try_from(i.as_ref()).map_err(|e| r.wrap_syntax_error(SyntaxError::NumberOutOfRange(e.0)))?)
}

pub struct ValueStream<'de, 'dec, R: Reader<'de>, D: Domain, VR: ValueReader<D>, Dec: DomainDecode<D>> {
    pub reader: R,
    pub read_annotations: bool,
    pub dec: &'dec mut Dec,
    phantom: PhantomData<&'de (D, VR)>,
}

impl<'de, 'dec, R: Reader<'de>, D: Domain, VR: ValueReader<D>, Dec: DomainDecode<D>>
    ValueStream<'de, 'dec, R, D, VR, Dec>
{
    pub fn new(reader: R, dec: &'dec mut Dec) -> Self {
        ValueStream {
            reader,
            read_annotations: true,
            dec,
            phantom: PhantomData,
        }
    }

    pub fn read_annotations(mut self, read_annotations: bool) -> Self {
        self.read_annotations = read_annotations;
        self
    }

    pub fn read_all(&mut self) -> ReaderResult<Vec<Value<D>>> {
        self.collect()
    }
}

impl<'de, 'dec, R: Reader<'de>, D: Domain, VR: ValueReader<D>, Dec: DomainDecode<D>>
    Iterator for ValueStream<'de, 'dec, R, D, VR, Dec>
{
    type Item = ReaderResult<Value<D>>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.reader.has_next() {
            Err(e) => Some(Err(e)),
            Ok(true) => Some(VR::read(&mut self.reader, self.read_annotations, self.dec)),
            Ok(false) => None,
        }
    }
}

pub struct IOValueStream<'de, R: Reader<'de>, VR: IOValueReader> {
    pub reader: R,
    pub read_annotations: bool,
    phantom: PhantomData<&'de VR>,
}

impl<'de, R: Reader<'de>, VR: IOValueReader> IOValueStream<'de, R, VR> {
    pub fn new(reader: R) -> Self {
        IOValueStream {
            reader,
            read_annotations: true,
            phantom: PhantomData,
        }
    }

    pub fn read_annotations(mut self, read_annotations: bool) -> Self {
        self.read_annotations = read_annotations;
        self
    }

    pub fn read_all(&mut self) -> ReaderResult<Vec<IOValue>> {
        self.collect()
    }
}
impl<'de, R: Reader<'de>, VR: IOValueReader> Iterator for IOValueStream<'de, R, VR> {
    type Item = ReaderResult<IOValue>;

    fn next(&mut self) -> Option<Self::Item> {
        match self.reader.has_next() {
            Err(e) => Some(Err(e)),
            Ok(true) => Some(VR::read_iovalue(&mut self.reader, self.read_annotations)),
            Ok(false) => None,
        }
    }
}