333 lines
10 KiB
Rust
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()),
|
|
}
|
|
}
|
|
}
|
|
}
|