preserves/implementations/rust/preserves/src/reader.rs

169 lines
6.5 KiB
Rust

use std::borrow::Cow;
use std::convert::TryFrom;
use std::io;
use crate::Atom;
use crate::BinarySource;
use crate::CompoundClass;
use crate::SignedInteger;
use crate::ValueClass;
use crate::boundary as B;
use crate::error::Error;
use crate::error::ExpectedKind;
use crate::error::io_eof;
pub type ReaderResult<T> = std::result::Result<T, Error>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum NextToken {
Annotation,
Value(ValueClass),
}
pub trait Reader<'de> {
fn peek_class(&mut self) -> io::Result<Option<NextToken>>;
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 skip_atom(&mut self) -> io::Result<()> {
let _ = self.next_atom()?;
Ok(())
}
fn skip_annotations(&mut self) -> io::Result<Option<ValueClass>> {
loop {
match self.peek_class()? {
None => return Ok(None),
Some(NextToken::Value(v)) => return Ok(Some(v)),
Some(NextToken::Annotation) => {
self.open_annotation()?;
self.skip_value()?;
self.close_annotation()?;
}
}
}
}
fn skip_value(&mut self) -> io::Result<()> {
// TODO efficient skipping in specific impls of this trait
match self.skip_annotations()?.ok_or_else(io_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 mut b = B::start(B::Item::RecordLabel);
self.boundary(&b)?;
self.skip_value()?;
while !self.close_compound(&mut b, &B::Item::RecordField)? {
self.skip_value()?;
}
Ok(())
}
ValueClass::Compound(CompoundClass::Sequence) => {
self.open_sequence()?;
let mut b = B::Type::default();
while !self.close_compound(&mut b, &B::Item::SequenceValue)? {
self.skip_value()?;
}
Ok(())
}
ValueClass::Compound(CompoundClass::Set) => {
self.open_set()?;
let mut b = B::Type::default();
while !self.close_compound(&mut b, &B::Item::SetValue)? {
self.skip_value()?;
}
Ok(())
}
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> { 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_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>
{
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(Error::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(Error::MissingItem)
}
}
fn ensure_complete(&mut self, mut b: B::Type, i: &B::Item) -> ReaderResult<()> {
if !self.close_compound(&mut b, i)? {
Err(Error::MissingCloseDelimiter)
} else {
Ok(())
}
}
fn specialized(&mut self) -> Option<(&str, &mut dyn BinarySource<'de>)> { None }
}