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

333 lines
10 KiB
Rust

use num::bigint::BigInt;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::io::{Read, Error};
use super::constants::{Op, InvalidOp, AtomMinor, CompoundMinor};
use super::value::{Value, NestedValue, IOValue, UnwrappedIOValue, Map, Set};
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug)]
enum PeekState {
Eof,
Empty,
Full(u8),
}
pub type DecodePlaceholderMap = Map<usize, UnwrappedIOValue>;
pub trait Reader {
fn next(
&mut self,
placeholders: Option<&DecodePlaceholderMap>,
read_annotations: bool,
) -> Result<IOValue>;
}
impl<'re, R: Reader> Reader for &'re mut R {
fn next(
&mut self,
placeholders: Option<&DecodePlaceholderMap>,
read_annotations: bool,
) -> Result<IOValue> {
(*self).next(placeholders, read_annotations)
}
}
pub struct BinaryReader<'a, R: Read> {
read: &'a mut R,
buf: PeekState,
}
struct ConfiguredBinaryReader<'de, 'pl, 'a, R: Read> {
reader: &'de mut BinaryReader<'a, R>,
placeholders: Option<&'pl DecodePlaceholderMap>,
read_annotations: bool,
}
struct CountedStream<'de, 'pl, 'a, R: Read> {
reader: ConfiguredBinaryReader<'de, 'pl, 'a, R>,
count: usize,
}
impl<'de, 'pl, 'a, R: Read> Iterator for CountedStream<'de, 'pl, 'a, R>
{
type Item = Result<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
if self.count == 0 { return None }
self.count -= 1;
Some(self.reader.reader.next(self.reader.placeholders, self.reader.read_annotations))
}
}
struct DelimitedStream<'de, 'pl, 'a, R: Read> {
reader: ConfiguredBinaryReader<'de, 'pl, 'a, R>,
}
impl<'de, 'pl, 'a, R: Read> Iterator for DelimitedStream<'de, 'pl, 'a, R>
{
type Item = Result<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
match self.reader.reader.peekend() {
Err(e) => Some(Err(e)),
Ok(true) => None,
Ok(false) => Some(self.reader.reader.next(self.reader.placeholders, self.reader.read_annotations)),
}
}
}
pub fn decodeop(b: u8) -> Result<(Op, u8)> {
Ok((Op::try_from(b >> 4)?, b & 15))
}
pub fn decodeint(bs: &[u8]) -> BigInt {
BigInt::from_signed_bytes_be(bs)
}
pub fn decodestr(bs: &[u8]) -> Result<&str> {
std::str::from_utf8(bs).map_err(|_| err("Invalid UTF-8"))
}
pub fn decodebinary(minor: AtomMinor, bs: Vec<u8>) -> Result<IOValue> {
match minor {
AtomMinor::SignedInteger => Ok(Value::from(decodeint(&bs)).wrap()),
AtomMinor::String => Ok(Value::from(decodestr(&bs)?).wrap()),
AtomMinor::ByteString => Ok(Value::ByteString(bs.to_vec()).wrap()),
AtomMinor::Symbol => Ok(Value::symbol(decodestr(&bs)?).wrap()),
}
}
pub fn decodecompound<I: Iterator<Item = Result<IOValue>>>(minor: CompoundMinor, mut iter: I) ->
Result<IOValue>
{
match minor {
CompoundMinor::Record =>
match iter.next() {
None => Err(err("Too few elements in encoded record")),
Some(labelres) => {
let label = labelres?;
Ok(Value::record(label, iter.collect::<Result<Vec<IOValue>>>()?).wrap())
}
}
CompoundMinor::Sequence => {
Ok(Value::Sequence(iter.collect::<Result<Vec<IOValue>>>()?).wrap())
}
CompoundMinor::Set => {
let mut s = Set::new();
for res in iter { s.insert(res?); }
Ok(Value::Set(s).wrap())
}
CompoundMinor::Dictionary => {
let mut d = Map::new();
while let Some(kres) = iter.next() {
let k = kres?;
match iter.next() {
Some(vres) => {
let v = vres?;
d.insert(k, v);
}
None => return Err(err("Missing dictionary value")),
}
}
Ok(Value::Dictionary(d).wrap())
}
}
}
pub fn eof() -> Error {
Error::new(std::io::ErrorKind::UnexpectedEof, "EOF")
}
pub fn err(s: &str) -> Error {
Error::new(std::io::ErrorKind::InvalidData, s)
}
pub fn is_syntax_error(e: &Error) -> bool {
match e.kind() {
std::io::ErrorKind::InvalidData => true,
_ => false,
}
}
pub fn is_eof_error(e: &Error) -> bool {
match e.kind() {
std::io::ErrorKind::UnexpectedEof => true,
_ => false,
}
}
impl<'a, R: Read> BinaryReader<'a, R> {
pub fn new(read: &'a mut R) -> Self {
BinaryReader {
read,
buf: PeekState::Empty,
}
}
fn prime(&mut self) -> Result<()> {
if let PeekState::Empty = self.buf {
let b = &mut [0];
match self.read.read(b)? {
0 => self.buf = PeekState::Eof,
1 => self.buf = PeekState::Full(b[0]),
_ => unreachable!(),
}
}
Ok(())
}
pub fn skip(&mut self) -> Result<()> {
self.prime()?;
if let PeekState::Full(_) = self.buf {
self.buf = PeekState::Empty;
}
Ok(())
}
pub fn peek(&mut self) -> Result<u8> {
self.prime()?;
match self.buf {
PeekState::Eof => Err(eof()),
PeekState::Empty => unreachable!(),
PeekState::Full(b) => Ok(b),
}
}
pub fn read(&mut self) -> Result<u8> {
let v = self.peek()?;
if let PeekState::Full(_) = self.buf {
self.buf = PeekState::Empty;
}
Ok(v)
}
pub fn readbytes(&mut self, bs: &mut [u8]) -> Result<()> {
match self.buf {
PeekState::Eof => unreachable!(),
PeekState::Empty => (),
PeekState::Full(_) => unreachable!(),
};
self.read.read_exact(bs)
}
pub fn varint(&mut self) -> Result<usize> {
let v = self.read()?;
if v < 128 {
Ok(usize::from(v))
} else {
Ok(self.varint()? * 128 + usize::from(v - 128))
}
}
pub fn wirelength(&mut self, arg: u8) -> Result<usize> {
if arg < 15 {
Ok(usize::from(arg))
} else {
self.varint()
}
}
pub fn peekend(&mut self) -> Result<bool> {
if self.peek()? == 4 {
self.skip()?;
Ok(true)
} else {
Ok(false)
}
}
}
impl<'re, 'a, R: Read> Reader for BinaryReader<'a, R> {
fn next(
&mut self,
placeholders: Option<&DecodePlaceholderMap>,
read_annotations: bool
) ->
Result<IOValue>
{
loop {
return match decodeop(self.read()?)? {
(Op::Misc(0), 0) => Ok(Value::from(false).wrap()),
(Op::Misc(0), 1) => Ok(Value::from(true).wrap()),
(Op::Misc(0), 2) => {
let mut bs = [0; 4];
self.readbytes(&mut bs)?;
Ok(Value::from(f32::from_bits(u32::from_be_bytes(bs.try_into().unwrap()))).wrap())
}
(Op::Misc(0), 3) => {
let mut bs = [0; 8];
self.readbytes(&mut bs)?;
Ok(Value::from(f64::from_bits(u64::from_be_bytes(bs.try_into().unwrap()))).wrap())
}
(Op::Misc(0), 5) => {
if read_annotations {
let mut annotations = vec![self.next(placeholders, read_annotations)?];
while decodeop(self.peek()?)? == (Op::Misc(0), 5) {
self.skip()?;
annotations.push(self.next(placeholders, read_annotations)?);
}
let v = self.next(placeholders, read_annotations)?;
assert!(v.annotations().is_empty());
Ok(IOValue::wrap_ann(annotations, v.value_owned()))
} else {
let _ = self.next(placeholders, read_annotations)?;
continue;
}
}
(Op::Misc(0), _) => Err(err("Invalid format A encoding")),
(Op::Misc(1), arg) => {
let n = self.wirelength(arg)?;
match placeholders.and_then(|m| m.get(&n)) {
Some(v) => Ok(v.clone().wrap()),
None => Err(err("Invalid Preserves placeholder")),
}
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Atom(minor) => {
let mut bs = Vec::with_capacity(256);
while !self.peekend()? {
match self.next(placeholders, false)?.value().as_bytestring() {
Some(chunk) => bs.extend_from_slice(chunk),
None => return Err(err("Unexpected non-binary chunk")),
}
}
decodebinary(minor, bs)
}
Op::Compound(minor) => decodecompound(minor, DelimitedStream {
reader: ConfiguredBinaryReader {
reader: self,
placeholders,
read_annotations,
},
}),
_ => Err(err("Invalid format C start byte")),
}
(Op::Misc(3), arg) => {
let n = if arg > 12 { i32::from(arg) - 16 } else { i32::from(arg) };
Ok(Value::from(n).wrap())
}
(Op::Misc(_), _) => unreachable!(),
(Op::Atom(minor), arg) => {
let count = self.wirelength(arg)?;
let mut bs = vec![0; count];
self.readbytes(&mut bs)?;
decodebinary(minor, bs)
}
(Op::Compound(minor), arg) => {
let count = self.wirelength(arg)?;
decodecompound(minor, CountedStream {
reader: ConfiguredBinaryReader {
reader: self,
placeholders,
read_annotations,
},
count,
})
}
(Op::Reserved(3), 15) => continue,
(Op::Reserved(_), _) => Err(InvalidOp.into()),
}
}
}
}