321 lines
12 KiB
Rust
321 lines
12 KiB
Rust
use std::borrow::Cow;
|
|
use std::convert::TryFrom;
|
|
use std::io;
|
|
use std::marker::PhantomData;
|
|
|
|
use crate::BinarySource;
|
|
use crate::CompoundClass;
|
|
use crate::SignedInteger;
|
|
use crate::Value;
|
|
use crate::ValueClass;
|
|
use crate::boundary as B;
|
|
use crate::domain::Domain;
|
|
use crate::domain::DomainDecode;
|
|
use crate::domain::IOValueDomainCodec;
|
|
use crate::error::Error;
|
|
use crate::error::ExpectedKind;
|
|
use crate::error::io_eof;
|
|
use crate::repr::Annotations;
|
|
use crate::repr::Atom;
|
|
use crate::repr::Embedded;
|
|
use crate::repr::IOValue;
|
|
use crate::repr::Map;
|
|
use crate::repr::Record;
|
|
use crate::repr::Set;
|
|
use crate::repr::ValueImpl;
|
|
|
|
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 gather_annotations(&mut self) -> io::Result<Option<(Vec<IOValue>, ValueClass)>> {
|
|
let mut anns = Vec::new();
|
|
loop {
|
|
match self.peek_class()? {
|
|
None => return Ok(None),
|
|
Some(NextToken::Value(v)) => return Ok(Some((anns, v))),
|
|
Some(NextToken::Annotation) => {
|
|
self.open_annotation()?;
|
|
anns.push(self.next_iovalue(true)?);
|
|
self.close_annotation()?;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn next<D: Domain, Dec: DomainDecode<D>>(
|
|
&mut self,
|
|
read_annotations: bool,
|
|
dec: &mut Dec,
|
|
) -> io::Result<Value<D>>
|
|
{
|
|
let (anns, v) = match read_annotations {
|
|
true => self.gather_annotations()?.ok_or_else(io_eof)?,
|
|
false => (Vec::new(), self.skip_annotations()?.ok_or_else(io_eof)?),
|
|
};
|
|
let value = match v {
|
|
ValueClass::Atomic(_) =>
|
|
self.next_atom()?.into_value(),
|
|
ValueClass::Embedded => {
|
|
self.open_embedded()?;
|
|
let v = dec.decode_embedded(self, read_annotations)?;
|
|
self.close_embedded()?;
|
|
Value::new(Embedded::new(v))
|
|
}
|
|
ValueClass::Compound(CompoundClass::Record) => {
|
|
let mut vs = Vec::new();
|
|
self.open_record()?;
|
|
let mut b = B::start(B::Item::RecordLabel);
|
|
self.boundary(&b)?;
|
|
vs.push(self.next(read_annotations, dec)?);
|
|
while !self.close_compound(&mut b, &B::Item::RecordField)? {
|
|
vs.push(self.next(read_annotations, dec)?);
|
|
}
|
|
Value::new(Record::_from_vec(vs))
|
|
}
|
|
ValueClass::Compound(CompoundClass::Sequence) => {
|
|
let mut vs = Vec::new();
|
|
self.open_sequence()?;
|
|
let mut b = B::Type::default();
|
|
while !self.close_compound(&mut b, &B::Item::SequenceValue)? {
|
|
vs.push(self.next(read_annotations, dec)?);
|
|
}
|
|
Value::new(vs)
|
|
}
|
|
ValueClass::Compound(CompoundClass::Set) => {
|
|
let mut s = Set::new();
|
|
self.open_set()?;
|
|
let mut b = B::Type::default();
|
|
while !self.close_compound(&mut b, &B::Item::SetValue)? {
|
|
s.insert(self.next(read_annotations, dec)?);
|
|
}
|
|
Value::new(s)
|
|
}
|
|
ValueClass::Compound(CompoundClass::Dictionary) => {
|
|
let mut d = Map::new();
|
|
self.open_dictionary()?;
|
|
let mut b = B::Type::default();
|
|
while !self.close_compound(&mut b, &B::Item::DictionaryKey)? {
|
|
let k = self.next(read_annotations, dec)?;
|
|
b.shift(Some(B::Item::DictionaryValue));
|
|
self.boundary(&b)?;
|
|
d.insert(k, self.next(read_annotations, dec)?);
|
|
}
|
|
Value::new(d)
|
|
}
|
|
};
|
|
if anns.is_empty() {
|
|
Ok(value)
|
|
} else {
|
|
Ok(Annotations::new(value, anns))
|
|
}
|
|
}
|
|
|
|
fn next_iovalue(&mut self, read_annotations: bool) -> io::Result<IOValue>
|
|
{
|
|
Ok(self.next(read_annotations, &mut IOValueDomainCodec)?.into())
|
|
}
|
|
|
|
fn next_boolean(&mut self) -> ReaderResult<bool> {
|
|
self.next_iovalue(false)?.as_boolean().ok_or(Error::Expected(ExpectedKind::Boolean))
|
|
}
|
|
|
|
fn next_float(&mut self) -> ReaderResult<f32> {
|
|
self.next_iovalue(false)?.as_float().ok_or(Error::Expected(ExpectedKind::Float))
|
|
}
|
|
|
|
fn next_double(&mut self) -> ReaderResult<f64> {
|
|
self.next_iovalue(false)?.as_double().ok_or(Error::Expected(ExpectedKind::Double))
|
|
}
|
|
|
|
fn next_signedinteger(&mut self) -> ReaderResult<SignedInteger> {
|
|
Ok(self.next_iovalue(false)?.as_signed_integer().ok_or(Error::Expected(ExpectedKind::SignedInteger))?.into_owned().into())
|
|
}
|
|
|
|
fn next_i8(&mut self) -> ReaderResult<i8> { Ok(i8::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_u8(&mut self) -> ReaderResult<u8> { Ok(u8::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_i16(&mut self) -> ReaderResult<i16> { Ok(i16::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_u16(&mut self) -> ReaderResult<u16> { Ok(u16::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_i32(&mut self) -> ReaderResult<i32> { Ok(i32::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_u32(&mut self) -> ReaderResult<u32> { Ok(u32::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_i64(&mut self) -> ReaderResult<i64> { Ok(i64::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_u64(&mut self) -> ReaderResult<u64> { Ok(u64::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_i128(&mut self) -> ReaderResult<i128> { Ok(i128::try_from(&self.next_signedinteger()?)?) }
|
|
fn next_u128(&mut self) -> ReaderResult<u128> { Ok(u128::try_from(&self.next_signedinteger()?)?) }
|
|
|
|
fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> {
|
|
Ok(self.next_iovalue(false)?.as_string().ok_or(Error::Expected(ExpectedKind::String))?.into_owned().into())
|
|
}
|
|
|
|
fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
|
|
Ok(self.next_iovalue(false)?.as_bytestring().ok_or(Error::Expected(ExpectedKind::ByteString))?.into_owned().into())
|
|
}
|
|
|
|
fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> {
|
|
Ok(self.next_iovalue(false)?.as_symbol().ok_or(Error::Expected(ExpectedKind::Symbol))?.into_owned().into())
|
|
}
|
|
|
|
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 }
|
|
}
|
|
|
|
pub struct IOValues<'de, R: Reader<'de>> {
|
|
pub reader: R,
|
|
pub read_annotations: bool,
|
|
phantom: PhantomData<&'de ()>,
|
|
}
|
|
|
|
impl<'de, R: Reader<'de>> IOValues<'de, R> {
|
|
pub fn new(reader: R) -> Self {
|
|
IOValues {
|
|
reader,
|
|
read_annotations: false,
|
|
phantom: PhantomData,
|
|
}
|
|
}
|
|
|
|
pub fn read_annotations(mut self, read_annotations: bool) -> Self {
|
|
self.read_annotations = read_annotations;
|
|
self
|
|
}
|
|
}
|
|
|
|
impl<'de, R: Reader<'de>> std::iter::Iterator for IOValues<'de, R> {
|
|
type Item = io::Result<IOValue>;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
match self.reader.peek_class() {
|
|
Err(e) => Some(Err(e)),
|
|
Ok(None) => None,
|
|
Ok(Some(_)) => Some(self.reader.next_iovalue(self.read_annotations)),
|
|
}
|
|
}
|
|
}
|