169 lines
6.5 KiB
Rust
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 }
|
|
}
|