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

268 lines
8.0 KiB
Rust

use std::io::Read;
use std::convert::TryInto;
use crate::value::value::{Value, AValue, Set, Dictionary};
use num::bigint::BigInt;
pub type Result<V> = std::result::Result<V, Error>;
#[derive(Debug)]
pub enum Error {
Io(std::io::Error),
Syntax(&'static str),
Eof,
}
impl From<std::io::Error> for Error {
fn from(v: std::io::Error) -> Self {
Error::Io(v)
}
}
impl From<std::str::Utf8Error> for Error {
fn from(_v: std::str::Utf8Error) -> Self {
Error::Syntax("Invalid UTF-8")
}
}
impl Error {
pub fn is_io(&self) -> bool { if let Error::Io(_) = *self { true } else { false } }
pub fn is_syntax(&self) -> bool { if let Error::Syntax(_) = *self { true } else { false } }
pub fn is_eof(&self) -> bool { if let Error::Eof = *self { true } else { false } }
}
pub type PlaceholderMap = std::collections::BTreeMap<usize, Value>;
pub struct Decoder<R: Read> {
read: R,
index: usize,
buf: Box<Option<Option<u8>>>,
placeholders: PlaceholderMap,
}
impl<R: Read> Decoder<R> {
pub fn new(read: R, placeholders: Option<PlaceholderMap>) -> Self {
Decoder{
read,
index: 0,
buf: Box::new(None),
placeholders: placeholders.unwrap_or(PlaceholderMap::new())
}
}
fn prime_if_possible(&mut self) -> Result<()> {
match *self.buf {
None => {
let bs = &mut [0];
*self.buf = Some(match self.read.read(bs)? {
0 => None,
1 => {
self.index = self.index + 1;
Some(bs[0])
},
_ => panic!("buffer overrun")
})
}
Some(_) => ()
}
Ok(())
}
pub fn skip(&mut self) -> Result<()> {
self.prime_if_possible()?;
*self.buf = None;
Ok(())
}
pub fn peek(&mut self) -> Result<u8> {
self.prime_if_possible()?;
match *self.buf {
Some(Some(v)) => Ok(v),
Some(None) => Err(Error::Eof),
None => panic!()
}
}
pub fn read(&mut self) -> Result<u8> {
let v = self.peek()?;
self.skip()?;
Ok(v)
}
pub fn readbytes(&mut self, n: usize) -> Result<Vec<u8>> {
if (*self.buf).is_some() {
panic!();
}
let mut bs = vec![0; n];
match self.read.read_exact(&mut bs) {
Ok(()) => Ok(bs),
Err(e) =>
if e.kind() == std::io::ErrorKind::UnexpectedEof {
Err(Error::Eof)
} else {
Err(Error::from(e))
}
}
}
pub fn readvalues(&mut self, mut count: usize) -> Result<Vec<AValue>> {
let mut pieces: Vec<AValue> = Vec::new();
while count > 0 {
pieces.push(self.next()?);
count = count - 1;
}
Ok(pieces)
}
pub fn nextop(&mut self) -> Result<(u8, u8, u8)> {
let b = self.read()?;
let major = b >> 6;
let minor = (b >> 4) & 3;
let arg = b & 15;
Ok((major, minor, arg))
}
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)
}
}
pub fn decodeint(bs: &[u8]) -> BigInt {
BigInt::from_signed_bytes_be(bs)
}
pub fn decodebinary(minor: u8, bs: Vec<u8>) -> Result<AValue> {
Ok(match minor {
0 => Value::from(Self::decodeint(&bs)).wrap(),
1 => Value::from(std::str::from_utf8(&bs)?).wrap(),
2 => Value::from(bs).wrap(),
3 => Value::symbol(std::str::from_utf8(&bs)?).wrap(),
_ => panic!()
})
}
pub fn decodecompound(minor: u8, mut pieces: Vec<AValue>) -> Result<AValue> {
match minor {
0 =>
if pieces.len() == 0 {
Err(Error::Syntax("Too few elements in encoded record"))
} else {
let label = pieces.remove(0).rc();
Ok(Value::record(&label, pieces).wrap())
},
1 => Ok(Value::from(pieces).wrap()),
2 => {
let mut s = Set::new();
while let Some(v) = pieces.pop() {
s.insert(v);
}
Ok(Value::Set(s).wrap())
}
3 =>
if pieces.len() % 2 != 0 {
Err(Error::Syntax("Missing dictionary value"))
} else {
let mut d = Dictionary::new();
while let Some(v) = pieces.pop() {
let k = pieces.pop().unwrap();
d.insert(k, v);
}
Ok(Value::Dictionary(d).wrap())
},
_ => panic!()
}
}
pub fn binarystream(&mut self, minor: u8) -> Result<AValue> {
let mut bs: Vec<u8> = Vec::new();
while !self.peekend()? {
match self.next()?.1.as_bytestring() {
Some(chunk) => bs.extend_from_slice(chunk),
None => return Err(Error::Syntax("Unexpected non-binary chunk")),
}
}
Self::decodebinary(minor, bs)
}
pub fn valuestream(&mut self, minor: u8) -> Result<AValue> {
let mut pieces: Vec<AValue> = Vec::new();
while !self.peekend()? {
pieces.push(self.next()?);
}
Self::decodecompound(minor, pieces)
}
pub fn next(&mut self) -> Result<AValue> {
match self.nextop()? {
(0, 0, 0) => Ok(Value::from(false).wrap()),
(0, 0, 1) => Ok(Value::from(true).wrap()),
(0, 0, 2) => {
let bs: &[u8] = &self.readbytes(4)?;
Ok(Value::from(f32::from_bits(u32::from_be_bytes(bs.try_into().unwrap()))).wrap())
}
(0, 0, 3) => {
let bs: &[u8] = &self.readbytes(8)?;
Ok(Value::from(f64::from_bits(u64::from_be_bytes(bs.try_into().unwrap()))).wrap())
}
(0, 0, 5) => {
let a = self.next()?;
let mut v = self.next()?;
v.annotations_mut().push(a);
Ok(v)
}
(0, 0, _) => Err(Error::Syntax("Invalid format A encoding")),
(0, 1, arg) => {
let n = self.wirelength(arg)?;
match self.placeholders.get(&n) {
Some(v) => Ok(v.clone().wrap()),
None => Err(Error::Syntax("Invalid Preserves placeholder")),
}
}
(0, 2, arg) => {
let t = arg >> 2;
let n = arg & 3;
match t {
1 => self.binarystream(n),
2 => self.valuestream(n),
_ => Err(Error::Syntax("Invalid format C start byte")),
}
}
(0, 3, arg) => {
let n = if arg > 12 { i32::from(arg) - 16 } else { i32::from(arg) };
Ok(Value::from(n).wrap())
}
(0, _, _) => panic!(),
(1, minor, arg) => {
let n = self.wirelength(arg)?;
Self::decodebinary(minor, self.readbytes(n)?)
}
(2, minor, arg) => {
let n = self.wirelength(arg)?;
Self::decodecompound(minor, self.readvalues(n)?)
}
(3, _, _) => Err(Error::Syntax("Invalid lead byte (major 3)")),
(_, _, _) => panic!(),
}
}
}