367 lines
12 KiB
Rust
367 lines
12 KiB
Rust
use std::borrow::Cow;
|
|
use std::io::{Read, Error};
|
|
use std::marker::PhantomData;
|
|
use super::value::{NestedValue, IOValue};
|
|
use crate::error::{self, ExpectedKind, Received, io_eof};
|
|
|
|
pub type IOResult<T> = std::result::Result<T, Error>;
|
|
pub type ReaderResult<T> = std::result::Result<T, error::Error>;
|
|
|
|
pub trait Reader<'de> {
|
|
type CompoundInfo: Copy;
|
|
|
|
fn next(&mut self, read_annotations: bool) -> IOResult<Option<IOValue>>;
|
|
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<CompoundBody<Self::CompoundInfo>>;
|
|
fn open_sequence_or_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>>;
|
|
fn open_sequence(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>>;
|
|
fn open_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>>;
|
|
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>>;
|
|
fn close_compound_counted(&mut self, info: Self::CompoundInfo) -> ReaderResult<()>;
|
|
fn close_compound_stream(&mut self, info: Self::CompoundInfo) -> ReaderResult<bool>;
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
fn skip_value(&mut self) -> IOResult<()> {
|
|
// TODO efficient skipping in specific impls of this trait
|
|
let _ = self.demand_next(false)?;
|
|
Ok(())
|
|
}
|
|
|
|
fn demand_next(&mut self, read_annotations: bool) -> IOResult<IOValue> {
|
|
match self.next(read_annotations)? {
|
|
None => Err(io_eof()),
|
|
Some(v) => Ok(v)
|
|
}
|
|
}
|
|
|
|
fn next_boolean(&mut self) -> ReaderResult<bool> { self.demand_next(false)?.value().to_boolean() }
|
|
fn next_i8(&mut self) -> ReaderResult<i8> { self.demand_next(false)?.value().to_i8() }
|
|
fn next_u8(&mut self) -> ReaderResult<u8> { self.demand_next(false)?.value().to_u8() }
|
|
fn next_i16(&mut self) -> ReaderResult<i16> { self.demand_next(false)?.value().to_i16() }
|
|
fn next_u16(&mut self) -> ReaderResult<u16> { self.demand_next(false)?.value().to_u16() }
|
|
fn next_i32(&mut self) -> ReaderResult<i32> { self.demand_next(false)?.value().to_i32() }
|
|
fn next_u32(&mut self) -> ReaderResult<u32> { self.demand_next(false)?.value().to_u32() }
|
|
fn next_i64(&mut self) -> ReaderResult<i64> { self.demand_next(false)?.value().to_i64() }
|
|
fn next_u64(&mut self) -> ReaderResult<u64> { self.demand_next(false)?.value().to_u64() }
|
|
fn next_i128(&mut self) -> ReaderResult<i128> { self.demand_next(false)?.value().to_i128() }
|
|
fn next_u128(&mut self) -> ReaderResult<u128> { self.demand_next(false)?.value().to_u128() }
|
|
fn next_float(&mut self) -> ReaderResult<f32> { self.demand_next(false)?.value().to_float() }
|
|
fn next_double(&mut self) -> ReaderResult<f64> { self.demand_next(false)?.value().to_double() }
|
|
fn next_char(&mut self) -> ReaderResult<char> { self.demand_next(false)?.value().to_char() }
|
|
|
|
fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> {
|
|
Ok(Cow::Owned(self.demand_next(false)?.value().to_string()?.to_owned()))
|
|
}
|
|
|
|
fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
|
|
Ok(Cow::Owned(self.demand_next(false)?.value().to_bytestring()?.to_owned()))
|
|
}
|
|
|
|
fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> {
|
|
Ok(Cow::Owned(self.demand_next(false)?.value().to_symbol()?.to_owned()))
|
|
}
|
|
|
|
fn open_option(&mut self) ->
|
|
ReaderResult<(bool, CompoundBody<Self::CompoundInfo>)>
|
|
where
|
|
Self: Sized
|
|
{
|
|
let mut compound_body = self.open_record(None)?;
|
|
let label: &str = &compound_body.next_symbol(self)?.ok_or(error::Error::MissingItem)?;
|
|
match label {
|
|
"None" => Ok((false, compound_body)),
|
|
"Some" => Ok((true, compound_body)),
|
|
_ => Err(error::Error::Expected(ExpectedKind::Option,
|
|
Received::ReceivedRecordWithLabel(label.to_owned()))),
|
|
}
|
|
}
|
|
|
|
fn open_simple_record(&mut self, name: &str, arity: Option<usize>) ->
|
|
ReaderResult<CompoundBody<Self::CompoundInfo>>
|
|
where
|
|
Self: Sized
|
|
{
|
|
let mut compound_body = self.open_record(arity)?;
|
|
let label: &str = &compound_body.next_symbol(self)?.ok_or(error::Error::MissingItem)?;
|
|
if label == name {
|
|
Ok(compound_body)
|
|
} else {
|
|
Err(error::Error::Expected(ExpectedKind::SimpleRecord(name.to_owned(), arity),
|
|
Received::ReceivedRecordWithLabel(label.to_owned())))
|
|
}
|
|
}
|
|
|
|
fn configured(self, read_annotations: bool) -> ConfiguredReader<'de, Self>
|
|
where
|
|
Self: std::marker::Sized
|
|
{
|
|
ConfiguredReader {
|
|
reader: self,
|
|
read_annotations,
|
|
phantom: PhantomData,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<'r, 'de, R: Reader<'de>> Reader<'de> for &'r mut R {
|
|
type CompoundInfo = R::CompoundInfo;
|
|
|
|
fn next(&mut self, read_annotations: bool) -> IOResult<Option<IOValue>> {
|
|
(*self).next(read_annotations)
|
|
}
|
|
|
|
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
|
|
(*self).open_record(arity)
|
|
}
|
|
|
|
fn open_sequence_or_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
|
|
(*self).open_sequence_or_set()
|
|
}
|
|
|
|
fn open_sequence(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
|
|
(*self).open_sequence()
|
|
}
|
|
|
|
fn open_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
|
|
(*self).open_set()
|
|
}
|
|
|
|
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
|
|
(*self).open_dictionary()
|
|
}
|
|
|
|
fn close_compound_counted(&mut self, info: Self::CompoundInfo) -> ReaderResult<()> {
|
|
(*self).close_compound_counted(info)
|
|
}
|
|
|
|
fn close_compound_stream(&mut self, info: Self::CompoundInfo) -> ReaderResult<bool> {
|
|
(*self).close_compound_stream(info)
|
|
}
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub struct CompoundBody<I: Copy> {
|
|
pub info: I,
|
|
pub limit: CompoundLimit,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum CompoundLimit {
|
|
Counted(usize),
|
|
Streaming,
|
|
Finished,
|
|
}
|
|
|
|
impl<I: Copy> CompoundBody<I> {
|
|
pub fn counted(info: I, size: usize) -> Self {
|
|
CompoundBody { info, limit: CompoundLimit::Counted(size) }
|
|
}
|
|
|
|
pub fn streaming(info: I) -> Self {
|
|
CompoundBody { info, limit: CompoundLimit::Streaming }
|
|
}
|
|
|
|
pub fn more_expected<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R) -> ReaderResult<bool> {
|
|
match self.limit {
|
|
CompoundLimit::Counted(ref mut n) =>
|
|
if *n == 0 {
|
|
read.close_compound_counted(self.info)?;
|
|
self.limit = CompoundLimit::Finished;
|
|
Ok(false)
|
|
} else {
|
|
*n = *n - 1;
|
|
Ok(true)
|
|
},
|
|
CompoundLimit::Streaming =>
|
|
Ok(!read.close_compound_stream(self.info)?),
|
|
CompoundLimit::Finished =>
|
|
Ok(false),
|
|
}
|
|
}
|
|
|
|
pub fn next_symbol<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R) -> ReaderResult<Option<Cow<'de, str>>> {
|
|
match self.more_expected(read)? {
|
|
false => Ok(None),
|
|
true => Ok(Some(read.next_symbol()?)),
|
|
}
|
|
}
|
|
|
|
pub fn next_value<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R, read_annotations: bool) ->
|
|
ReaderResult<Option<IOValue>>
|
|
{
|
|
match self.more_expected(read)? {
|
|
false => Ok(None),
|
|
true => Ok(Some(read.demand_next(read_annotations)?)),
|
|
}
|
|
}
|
|
|
|
pub fn remainder<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R, read_annotations: bool) ->
|
|
ReaderResult<Vec<IOValue>>
|
|
{
|
|
let mut result = Vec::new();
|
|
while let Some(v) = self.next_value(read, read_annotations)? {
|
|
result.push(v);
|
|
}
|
|
Ok(result)
|
|
}
|
|
|
|
pub fn skip_remainder<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R) ->
|
|
ReaderResult<()>
|
|
{
|
|
while let true = self.more_expected(read)? {
|
|
read.skip_value()?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn ensure_more_expected<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R) -> ReaderResult<()> {
|
|
if self.more_expected(read)? {
|
|
Ok(())
|
|
} else {
|
|
Err(error::Error::MissingItem)
|
|
}
|
|
}
|
|
|
|
pub fn ensure_complete<'de, R: Reader<'de, CompoundInfo = I>>(&mut self, read: &mut R) -> ReaderResult<()> {
|
|
if self.more_expected(read)? {
|
|
Err(error::Error::MissingCloseDelimiter)
|
|
} else {
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
pub trait BinarySource<'de> {
|
|
fn skip(&mut self) -> IOResult<()>;
|
|
fn peek(&mut self) -> IOResult<u8>;
|
|
fn readbytes(&mut self, count: usize) -> IOResult<Cow<'de, [u8]>>;
|
|
fn readbytes_into(&mut self, bs: &mut [u8]) -> IOResult<()>;
|
|
}
|
|
|
|
pub struct IOBinarySource<'a, R: Read> {
|
|
pub read: &'a mut R,
|
|
pub buf: Option<u8>,
|
|
}
|
|
|
|
impl<'a, R: Read> IOBinarySource<'a, R> {
|
|
pub fn new(read: &'a mut R) -> Self {
|
|
IOBinarySource { read, buf: None }
|
|
}
|
|
}
|
|
|
|
impl<'de, 'a, R: Read> BinarySource<'de> for IOBinarySource<'a, R> {
|
|
fn skip(&mut self) -> IOResult<()> {
|
|
if let None = self.buf { unreachable!(); }
|
|
self.buf = None;
|
|
Ok(())
|
|
}
|
|
|
|
fn peek(&mut self) -> IOResult<u8> {
|
|
match self.buf {
|
|
Some(b) => Ok(b),
|
|
None => {
|
|
let b = &mut [0];
|
|
match self.read.read(b)? {
|
|
0 => Err(io_eof()),
|
|
1 => {
|
|
self.buf = Some(b[0]);
|
|
Ok(b[0])
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
fn readbytes(&mut self, count: usize) -> IOResult<Cow<'de, [u8]>> {
|
|
if let Some(_) = self.buf { unreachable!(); }
|
|
let mut bs = vec![0; count];
|
|
self.read.read_exact(&mut bs)?;
|
|
Ok(Cow::Owned(bs))
|
|
}
|
|
|
|
fn readbytes_into(&mut self, bs: &mut [u8]) -> IOResult<()> {
|
|
if let Some(_) = self.buf { unreachable!(); }
|
|
self.read.read_exact(bs)
|
|
}
|
|
}
|
|
|
|
pub struct BytesBinarySource<'de> {
|
|
pub bytes: &'de [u8],
|
|
pub index: usize,
|
|
}
|
|
|
|
impl<'de> BytesBinarySource<'de> {
|
|
pub fn new(bytes: &'de [u8]) -> Self {
|
|
BytesBinarySource { bytes, index: 0 }
|
|
}
|
|
}
|
|
|
|
impl<'de> BinarySource<'de> for BytesBinarySource<'de> {
|
|
fn skip(&mut self) -> IOResult<()> {
|
|
if self.index >= self.bytes.len() { unreachable!(); }
|
|
self.index += 1;
|
|
Ok(())
|
|
}
|
|
|
|
fn peek(&mut self) -> IOResult<u8> {
|
|
if self.index >= self.bytes.len() {
|
|
Err(io_eof())
|
|
} else {
|
|
Ok(self.bytes[self.index])
|
|
}
|
|
}
|
|
|
|
fn readbytes(&mut self, count: usize) -> IOResult<Cow<'de, [u8]>> {
|
|
if self.index + count > self.bytes.len() {
|
|
Err(io_eof())
|
|
} else {
|
|
let bs = &self.bytes[self.index..self.index+count];
|
|
self.index += count;
|
|
Ok(Cow::Borrowed(bs))
|
|
}
|
|
}
|
|
|
|
fn readbytes_into(&mut self, bs: &mut [u8]) -> IOResult<()> {
|
|
let count = bs.len();
|
|
if self.index + count > self.bytes.len() {
|
|
Err(io_eof())
|
|
} else {
|
|
bs.copy_from_slice(&self.bytes[self.index..self.index+count]);
|
|
self.index += count;
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct ConfiguredReader<'de, R: Reader<'de>> {
|
|
pub reader: R,
|
|
pub read_annotations: bool,
|
|
phantom: PhantomData<&'de ()>,
|
|
}
|
|
|
|
impl<'de, R: Reader<'de>> ConfiguredReader<'de, R> {
|
|
pub fn new(reader: R) -> Self {
|
|
reader.configured(true)
|
|
}
|
|
|
|
pub fn set_read_annotations(&mut self, read_annotations: bool) {
|
|
self.read_annotations = read_annotations
|
|
}
|
|
|
|
pub fn demand_next(&mut self) -> IOResult<IOValue> {
|
|
self.reader.demand_next(self.read_annotations)
|
|
}
|
|
}
|
|
|
|
impl<'de, R: Reader<'de>> std::iter::Iterator for ConfiguredReader<'de, R> {
|
|
type Item = IOResult<IOValue>;
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
match self.reader.next(self.read_annotations) {
|
|
Err(e) => Some(Err(e)),
|
|
Ok(None) => None,
|
|
Ok(Some(v)) => Some(Ok(v)),
|
|
}
|
|
}
|
|
}
|