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 = std::result::Result; #[derive(Debug)] enum PeekState { Eof, Empty, Full(u8), } pub type DecodePlaceholderMap = Map; pub trait Reader { fn next( &mut self, placeholders: Option<&DecodePlaceholderMap>, read_annotations: bool, ) -> Result; } impl<'re, R: Reader> Reader for &'re mut R { fn next( &mut self, placeholders: Option<&DecodePlaceholderMap>, read_annotations: bool, ) -> Result { (*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; fn next(&mut self) -> Option { 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; fn next(&mut self) -> Option { 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) -> Result { 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>>(minor: CompoundMinor, mut iter: I) -> Result { 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::>>()?).wrap()) } } CompoundMinor::Sequence => { Ok(Value::Sequence(iter.collect::>>()?).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 { self.prime()?; match self.buf { PeekState::Eof => Err(eof()), PeekState::Empty => unreachable!(), PeekState::Full(b) => Ok(b), } } pub fn read(&mut self) -> Result { 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 { 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 { if arg < 15 { Ok(usize::from(arg)) } else { self.varint() } } pub fn peekend(&mut self) -> Result { 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 { 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()), } } } }