Refactor to extract packed format from general traits. Regression in encode performance?

This commit is contained in:
Tony Garnock-Jones 2020-07-08 14:34:25 +02:00
parent 3f76049f13
commit 28101cc7d1
14 changed files with 1277 additions and 1117 deletions

View File

@ -1,5 +1,5 @@
use criterion::{criterion_group, criterion_main, Criterion};
use preserves::value::{self, decoder, encoder, reader, reader::Reader};
use preserves::value::{self, decoder, encoder, PackedReader, PackedWriter, reader::Reader};
use preserves::{de, ser};
use std::io::Read;
use std::io::BufReader;
@ -38,7 +38,7 @@ pub fn bench_encoder(c: &mut Criterion) {
let v = decoder::from_read(&mut fh).demand_next().unwrap();
c.bench_function("encode samples.bin", |b| b.iter_with_large_drop(|| {
let mut bs = vec![];
encoder::Encoder::new(&mut bs).write(&v).unwrap();
encoder::Encoder::new(&mut PackedWriter(&mut bs)).write(&v).unwrap();
bs
}));
}
@ -56,7 +56,7 @@ pub fn bench_ser(c: &mut Criterion) {
let v: TestCases = de::from_read(&mut fh).unwrap();
c.bench_function("serialize samples.bin", |b| b.iter_with_large_drop(|| {
let mut bs = vec![];
ser::to_writer(&mut bs, &v).unwrap();
ser::to_writer(&mut PackedWriter(&mut bs), &v).unwrap();
bs
}));
}
@ -74,7 +74,7 @@ pub fn bench_ser_encoder(c: &mut Criterion) {
let v: TestCases = de::from_read(&mut fh).unwrap();
c.bench_function("serialize-then-encode samples.bin", |b| b.iter_with_large_drop(|| {
let mut bs = vec![];
encoder::Encoder::new(&mut bs).write(&value::ser::to_value(&v)).unwrap();
encoder::Encoder::new(&mut PackedWriter(&mut bs)).write(&value::ser::to_value(&v)).unwrap();
bs
}));
}
@ -85,7 +85,7 @@ pub fn large_testdata_decoder_with_ann(c: &mut Criterion) {
let mut bs = vec![];
fh.read_to_end(&mut bs).ok();
b.iter(|| {
let mut r = reader::from_bytes(&bs[..]);
let mut r = PackedReader::from_bytes(&bs[..]);
while let Some(_) = r.next(true).unwrap() {}
})
});
@ -97,7 +97,7 @@ pub fn large_testdata_decoder_without_ann(c: &mut Criterion) {
let mut bs = vec![];
fh.read_to_end(&mut bs).ok();
b.iter(|| {
let mut r = reader::from_bytes(&bs[..]);
let mut r = PackedReader::from_bytes(&bs[..]);
while let Some(_) = r.next(false).unwrap() {}
})
});
@ -107,13 +107,14 @@ pub fn large_testdata_encoder(c: &mut Criterion) {
c.bench_function("encode testdata.bin", |b| {
let mut fh = BufReader::new(std::fs::File::open("benches/testdata.bin").unwrap());
let mut vs = vec![];
let mut r = reader::from_read(&mut fh);
let mut r = PackedReader::from_read(&mut fh);
while let Some(v) = r.next(true).unwrap() {
vs.push(v);
}
b.iter_with_large_drop(|| {
let mut bs = vec![];
let mut e = encoder::Encoder::new(&mut bs);
let mut w = PackedWriter(&mut bs);
let mut e = encoder::Encoder::new(&mut w);
for v in &vs {
e.write(&v).unwrap();
}

View File

@ -2,7 +2,8 @@ use serde::Deserialize;
use serde::de::{Visitor, SeqAccess, MapAccess, EnumAccess, VariantAccess, DeserializeSeed};
use std::borrow::Cow;
use std::marker::PhantomData;
use super::value::reader::{Reader, BinaryReader, IOBinarySource, BytesBinarySource, CompoundBody};
use super::value::PackedReader;
use super::value::reader::{Reader, IOBinarySource, BytesBinarySource, CompoundBody};
pub use super::error::Error;
@ -18,7 +19,7 @@ pub fn from_bytes<'de, T>(bytes: &'de [u8]) ->
where
T: Deserialize<'de>
{
from_reader(&mut BinaryReader::new(BytesBinarySource::new(bytes)))
from_reader(&mut PackedReader::new(BytesBinarySource::new(bytes)))
}
pub fn from_read<'de, 'r, IOR: std::io::Read, T>(read: &'r mut IOR) ->
@ -26,7 +27,7 @@ pub fn from_read<'de, 'r, IOR: std::io::Read, T>(read: &'r mut IOR) ->
where
T: Deserialize<'de>
{
from_reader(&mut BinaryReader::new(IOBinarySource::new(read)))
from_reader(&mut PackedReader::new(IOBinarySource::new(read)))
}
pub fn from_reader<'r, 'de, R: Reader<'de>, T>(read: &'r mut R) ->
@ -260,11 +261,11 @@ impl<'r, 'de, 'a, R: Reader<'de>> serde::de::Deserializer<'de> for &'a mut Deser
pub struct Seq<'de, 'r, 'a, R: Reader<'de>> {
de: &'a mut Deserializer<'de, 'r, R>,
compound_body: CompoundBody,
compound_body: CompoundBody<R::CompoundInfo>,
}
impl<'de, 'r, 'a, R: Reader<'de>> Seq<'de, 'r, 'a, R> {
fn new(de: &'a mut Deserializer<'de, 'r, R>, compound_body: CompoundBody) -> Self {
fn new(de: &'a mut Deserializer<'de, 'r, R>, compound_body: CompoundBody<R::CompoundInfo>) -> Self {
Seq { de, compound_body }
}

View File

@ -12,6 +12,7 @@ pub enum Error {
MissingCloseDelimiter,
MissingItem,
Expected(ExpectedKind, Received),
StreamingSerializationUnsupported,
}
#[derive(Debug)]

View File

@ -390,6 +390,7 @@ mod serde_tests {
use crate::value::encoder::encode_bytes;
use crate::value::to_value;
use crate::value::{Value, IOValue, Map, Set};
use crate::value::packed::PackedWriter;
#[test] fn simple_to_value() {
use serde::Serialize;
@ -480,7 +481,7 @@ mod serde_tests {
assert_eq!(expected_bytes, v_bytes_1);
let mut v_bytes_2 = Vec::new();
v.serialize(&mut crate::ser::Serializer::new(&mut v_bytes_2)).unwrap();
v.serialize(&mut crate::ser::Serializer::new(&mut PackedWriter(&mut v_bytes_2))).unwrap();
println!("== v bytes = {:?}", v_bytes_2);
assert_eq!(v_bytes_1, v_bytes_2);

View File

@ -19,129 +19,145 @@ impl<'a, W: Writer> Serializer<'a, W> {
#[derive(Debug)]
pub struct SerializeCompound<'a, 'b, W: Writer> {
ser: &'a mut Serializer<'b, W>,
count: Option<usize>,
c: W::Compound,
}
#[derive(Debug)]
pub struct SerializeDictionary<'a, 'b, W: Writer> {
ser: &'a mut Serializer<'b, W>,
d: W::Dictionary,
key_p: Option<W::KeyPointer>,
}
impl<'a, 'b, W: Writer> serde::Serializer for &'a mut Serializer<'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
type SerializeSeq = SerializeCompound<'a, 'b, W>;
type SerializeTuple = SerializeCompound<'a, 'b, W>;
type SerializeTupleStruct = SerializeCompound<'a, 'b, W>;
type SerializeTupleVariant = SerializeCompound<'a, 'b, W>;
type SerializeMap = SerializeCompound<'a, 'b, W>;
type SerializeMap = SerializeDictionary<'a, 'b, W>;
type SerializeStruct = SerializeCompound<'a, 'b, W>;
type SerializeStructVariant = SerializeCompound<'a, 'b, W>;
fn serialize_bool(self, v: bool) -> Result<()> {
fn serialize_bool(self, v: bool) -> Result<Self::Ok> {
Ok(self.write.write_bool(v)?)
}
fn serialize_i8(self, v: i8) -> Result<()> {
fn serialize_i8(self, v: i8) -> Result<Self::Ok> {
Ok(self.write.write_i8(v)?)
}
fn serialize_i16(self, v: i16) -> Result<()> {
fn serialize_i16(self, v: i16) -> Result<Self::Ok> {
Ok(self.write.write_i16(v)?)
}
fn serialize_i32(self, v: i32) -> Result<()> {
fn serialize_i32(self, v: i32) -> Result<Self::Ok> {
Ok(self.write.write_i32(v)?)
}
fn serialize_i64(self, v: i64) -> Result<()> {
fn serialize_i64(self, v: i64) -> Result<Self::Ok> {
Ok(self.write.write_i64(v)?)
}
fn serialize_u8(self, v: u8) -> Result<()> {
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
Ok(self.write.write_u8(v)?)
}
fn serialize_u16(self, v: u16) -> Result<()> {
fn serialize_u16(self, v: u16) -> Result<Self::Ok> {
Ok(self.write.write_u16(v)?)
}
fn serialize_u32(self, v: u32) -> Result<()> {
fn serialize_u32(self, v: u32) -> Result<Self::Ok> {
Ok(self.write.write_u32(v)?)
}
fn serialize_u64(self, v: u64) -> Result<()> {
fn serialize_u64(self, v: u64) -> Result<Self::Ok> {
Ok(self.write.write_u64(v)?)
}
fn serialize_f32(self, v: f32) -> Result<()> {
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
Ok(self.write.write_f32(v)?)
}
fn serialize_f64(self, v: f64) -> Result<()> {
fn serialize_f64(self, v: f64) -> Result<Self::Ok> {
Ok(self.write.write_f64(v)?)
}
fn serialize_char(self, v: char) -> Result<()> {
self.write.open_record(1)?;
self.write.write_symbol("UnicodeScalar")?;
self.write.write_u32(v as u32)?;
Ok(self.write.close_record()?)
fn serialize_char(self, v: char) -> Result<Self::Ok> {
let mut c = self.write.start_record(1)?;
let p = self.write.write_symbol("UnicodeScalar")?;
self.write.extend_compound(&mut c, p)?;
let p = self.write.write_u32(v as u32)?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_str(self, v: &str) -> Result<()> {
fn serialize_str(self, v: &str) -> Result<Self::Ok> {
Ok(self.write.write_string(v)?)
}
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok> {
Ok(self.write.write_bytes(v)?)
}
fn serialize_none(self) -> Result<()> {
self.write.open_record(0)?;
self.write.write_symbol("None")?;
Ok(self.write.close_record()?)
fn serialize_none(self) -> Result<Self::Ok> {
let mut c = self.write.start_record(0)?;
let p = self.write.write_symbol("None")?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_some<T: ?Sized>(self, v: &T) -> Result<()> where T: Serialize {
self.write.open_record(1)?;
self.write.write_symbol("Some")?;
v.serialize(&mut *self)?;
Ok(self.write.close_record()?)
fn serialize_some<T: ?Sized>(self, v: &T) -> Result<Self::Ok> where T: Serialize {
let mut c = self.write.start_record(1)?;
let p = self.write.write_symbol("Some")?;
self.write.extend_compound(&mut c, p)?;
let p = v.serialize(&mut *self)?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_unit(self) -> Result<()> {
self.write.open_record(0)?;
self.write.write_symbol("tuple")?;
Ok(self.write.close_record()?)
fn serialize_unit(self) -> Result<Self::Ok> {
let mut c = self.write.start_record(0)?;
let p = self.write.write_symbol("tuple")?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_unit_struct(self, name: &'static str) -> Result<()> {
self.write.open_record(0)?;
self.write.write_symbol(name)?;
Ok(self.write.close_record()?)
fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok> {
let mut c = self.write.start_record(0)?;
let p = self.write.write_symbol(name)?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_unit_variant(self,
_name: &'static str,
_variant: u32,
variant_name: &'static str) ->
Result<()>
Result<Self::Ok>
{
self.write.open_record(0)?;
self.write.write_symbol(variant_name)?;
Ok(self.write.close_record()?)
let mut c = self.write.start_record(0)?;
let p = self.write.write_symbol(variant_name)?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_newtype_struct<T: ?Sized>(self, name: &'static str, value: &T) ->
Result<()> where T: Serialize
Result<Self::Ok> where T: Serialize
{
match super::value::magic::receive_output_value(name, value) {
Some(v) => {
Encoder::new(self.write).write(&v)?;
Ok(())
Ok(Encoder::new(self.write).write(&v)?)
}
None => {
// TODO: This is apparently discouraged, and we should apparently just serialize `value`?
self.write.open_record(1)?;
self.write.write_symbol(name)?;
value.serialize(&mut *self)?;
Ok(self.write.close_record()?)
let mut c = self.write.start_record(1)?;
let p = self.write.write_symbol(name)?;
self.write.extend_compound(&mut c, p)?;
let p = value.serialize(&mut *self)?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
}
}
@ -151,34 +167,41 @@ impl<'a, 'b, W: Writer> serde::Serializer for &'a mut Serializer<'b, W> {
_variant: u32,
variant_name: &'static str,
value: &T) ->
Result<()> where T: Serialize
Result<Self::Ok> where T: Serialize
{
self.write.open_record(1)?;
self.write.write_symbol(variant_name)?;
value.serialize(&mut *self)?;
Ok(self.write.close_record()?)
let mut c = self.write.start_record(1)?;
let p = self.write.write_symbol(variant_name)?;
self.write.extend_compound(&mut c, p)?;
let p = value.serialize(&mut *self)?;
self.write.extend_compound(&mut c, p)?;
Ok(self.write.end_compound(c)?)
}
fn serialize_seq(self, count: Option<usize>) -> Result<Self::SerializeSeq> {
match count {
Some(n) => self.write.open_sequence(n)?,
None => self.write.stream_sequence()?,
}
Ok(SerializeCompound { ser: self, count })
let c = match count {
Some(n) => self.write.start_sequence(n as u64)?,
None => match self.write.stream_sequence()? {
Some(c) => c,
None => return Err(Error::StreamingSerializationUnsupported),
}
};
Ok(SerializeCompound { ser: self, c })
}
fn serialize_tuple(self, count: usize) -> Result<Self::SerializeTuple> {
self.write.open_record(count)?;
self.write.write_symbol("tuple")?;
Ok(SerializeCompound { ser: self, count: Some(count) })
let mut c = self.write.start_record(count as u64)?;
let p = self.write.write_symbol("tuple")?;
self.write.extend_compound(&mut c, p)?;
Ok(SerializeCompound { ser: self, c })
}
fn serialize_tuple_struct(self, name: &'static str, count: usize) ->
Result<Self::SerializeTupleStruct>
{
self.write.open_record(count)?;
self.write.write_symbol(name)?;
Ok(SerializeCompound { ser: self, count: Some(count) })
let mut c = self.write.start_record(count as u64)?;
let p = self.write.write_symbol(name)?;
self.write.extend_compound(&mut c, p)?;
Ok(SerializeCompound { ser: self, c })
}
fn serialize_tuple_variant(self,
@ -188,23 +211,28 @@ impl<'a, 'b, W: Writer> serde::Serializer for &'a mut Serializer<'b, W> {
count: usize) ->
Result<Self::SerializeTupleVariant>
{
self.write.open_record(count)?;
self.write.write_symbol(variant_name)?;
Ok(SerializeCompound { ser: self, count: Some(count) })
let mut c = self.write.start_record(count as u64)?;
let p = self.write.write_symbol(variant_name)?;
self.write.extend_compound(&mut c, p)?;
Ok(SerializeCompound { ser: self, c })
}
fn serialize_map(self, count: Option<usize>) -> Result<Self::SerializeMap> {
match count {
Some(n) => self.write.open_dictionary(n)?,
None => self.write.stream_dictionary()?,
}
Ok(SerializeCompound { ser: self, count })
let d = match count {
Some(n) => self.write.start_dictionary(n as u64)?,
None => match self.write.stream_dictionary()? {
Some(d) => d,
None => return Err(Error::StreamingSerializationUnsupported),
}
};
Ok(SerializeDictionary { ser: self, d, key_p: None })
}
fn serialize_struct(self, name: &'static str, count: usize) -> Result<Self::SerializeStruct> {
self.write.open_record(count)?;
self.write.write_symbol(name)?;
Ok(SerializeCompound { ser: self, count: Some(count) })
let mut c = self.write.start_record(count as u64)?;
let p = self.write.write_symbol(name)?;
self.write.extend_compound(&mut c, p)?;
Ok(SerializeCompound { ser: self, c })
}
fn serialize_struct_variant(self,
@ -214,133 +242,122 @@ impl<'a, 'b, W: Writer> serde::Serializer for &'a mut Serializer<'b, W> {
count: usize) ->
Result<Self::SerializeStructVariant>
{
self.write.open_record(count)?;
self.write.write_symbol(variant_name)?;
Ok(SerializeCompound { ser: self, count: Some(count) })
let mut c = self.write.start_record(count as u64)?;
let p = self.write.write_symbol(variant_name)?;
self.write.extend_compound(&mut c, p)?;
Ok(SerializeCompound { ser: self, c })
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeMap for SerializeCompound<'a, 'b, W> {
type Ok = ();
impl<'a, 'b, W: Writer> serde::ser::SerializeMap for SerializeDictionary<'a, 'b, W> {
type Ok = W::Pointer;
type Error = Error;
fn serialize_key<T: ?Sized>(&mut self, key: &T) -> Result<()> where T: Serialize {
Ok(key.serialize(&mut *self.ser)?)
let kp1 = key.serialize(&mut *self.ser)?;
self.key_p = Some(self.ser.write.extend_dictionary_key(&mut self.d, kp1)?);
Ok(())
}
fn serialize_value<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: Serialize {
Ok(value.serialize(&mut *self.ser)?)
let vp1 = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_dictionary_value(&mut self.d, self.key_p.take().unwrap(), vp1)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_dictionary()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_dictionary(self.d)?)
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeStruct for SerializeCompound<'a, 'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, _name: &'static str, value: &T) -> Result<()>
where T: Serialize
{
Ok(value.serialize(&mut *self.ser)?)
let p = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_compound(&mut self.c, p)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_record()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_compound(self.c)?)
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeStructVariant for SerializeCompound<'a, 'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, _name: &'static str, value: &T) -> Result<()>
where T: Serialize
{
Ok(value.serialize(&mut *self.ser)?)
let p = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_compound(&mut self.c, p)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_record()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_compound(self.c)?)
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeTuple for SerializeCompound<'a, 'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: Serialize {
Ok(value.serialize(&mut *self.ser)?)
let p = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_compound(&mut self.c, p)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_record()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_compound(self.c)?)
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeTupleStruct for SerializeCompound<'a, 'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: Serialize {
Ok(value.serialize(&mut *self.ser)?)
let p = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_compound(&mut self.c, p)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_record()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_compound(self.c)?)
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeTupleVariant for SerializeCompound<'a, 'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: Serialize {
Ok(value.serialize(&mut *self.ser)?)
let p = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_compound(&mut self.c, p)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_record()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_compound(self.c)?)
}
}
impl<'a, 'b, W: Writer> serde::ser::SerializeSeq for SerializeCompound<'a, 'b, W> {
type Ok = ();
type Ok = W::Pointer;
type Error = Error;
fn serialize_element<T: ?Sized>(&mut self, value: &T) -> Result<()> where T: Serialize {
Ok(value.serialize(&mut *self.ser)?)
let p = value.serialize(&mut *self.ser)?;
Ok(self.ser.write.extend_compound(&mut self.c, p)?)
}
fn end(self) -> Result<()> {
match self.count {
None => Ok(self.ser.write.close_stream()?),
Some(_) => Ok(self.ser.write.close_sequence()?),
}
fn end(self) -> Result<Self::Ok> {
Ok(self.ser.write.end_compound(self.c)?)
}
}
pub fn to_writer<W: Writer, T: Serialize>(write: &mut W, value: &T) -> Result<()> {
pub fn to_writer<W: Writer, T: Serialize>(write: &mut W, value: &T) -> Result<W::Pointer> {
let mut ser: Serializer<'_, W> = Serializer::new(write);
value.serialize(&mut ser)
}

View File

@ -1,5 +1,6 @@
use std::marker::PhantomData;
use super::reader::{self, Reader, BinaryReader};
use super::packed::PackedReader;
use super::reader::{self, Reader};
use super::value::IOValue;
pub use super::reader::IOResult as Result;
@ -11,15 +12,15 @@ pub struct Decoder<'de, R: Reader<'de>> {
}
pub fn from_bytes<'de>(bytes: &'de [u8]) ->
Decoder<'de, BinaryReader<'de, reader::BytesBinarySource<'de>>>
Decoder<'de, PackedReader<'de, reader::BytesBinarySource<'de>>>
{
Decoder::new(reader::from_bytes(bytes))
Decoder::new(PackedReader::from_bytes(bytes))
}
pub fn from_read<'de, 'a, IOR: std::io::Read>(read: &'a mut IOR) ->
Decoder<'de, BinaryReader<'de, reader::IOBinarySource<'a, IOR>>>
Decoder<'de, PackedReader<'de, reader::IOBinarySource<'a, IOR>>>
{
Decoder::new(reader::from_read(read))
Decoder::new(PackedReader::from_read(read))
}
impl<'de, R: Reader<'de>> Decoder<'de, R> {

View File

@ -1,6 +1,7 @@
use super::value::{Value, NestedValue, Domain, IOValue, UnwrappedIOValue, Float, Double};
use super::signed_integer::SignedIntegerRepr;
use super::writer::Writer;
use super::packed::PackedWriter;
pub use super::writer::Result;
@ -10,7 +11,7 @@ pub struct Encoder<'a, W: Writer> {
pub fn encode_bytes(v: &IOValue) -> std::io::Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
Encoder::new(&mut buf).write(v)?;
Encoder::new(&mut PackedWriter(&mut buf)).write(v)?;
Ok(buf)
}
@ -19,18 +20,21 @@ impl<'a, W: Writer> Encoder<'a, W> {
Encoder { write }
}
pub fn write(&mut self, v: &IOValue) -> Result {
pub fn write(&mut self, v: &IOValue) -> Result<W::Pointer> {
match v.annotations().maybe_slice() {
None => (),
Some(anns) => for ann in anns {
self.write.write_annotation_prefix()?;
self.write(ann)?;
None => self.write_value(v.value()),
Some(anns) => {
let mut a = self.write.start_annotation()?;
for ann in anns {
self.write.extend_annotation(&mut a, ann)?;
}
let p = self.write_value(v.value())?;
self.write.end_annotation(a, p)
}
}
self.write_value(v.value())
}
pub fn write_value(&mut self, v: &UnwrappedIOValue) -> Result {
pub fn write_value(&mut self, v: &UnwrappedIOValue) -> Result<W::Pointer> {
match v {
Value::Boolean(b) => self.write.write_bool(*b),
Value::Float(Float(f)) => self.write.write_f32(*f),
@ -44,25 +48,40 @@ impl<'a, W: Writer> Encoder<'a, W> {
Value::ByteString(ref bs) => self.write.write_bytes(bs),
Value::Symbol(ref s) => self.write.write_symbol(s),
Value::Record(r) => {
self.write.open_record(r.arity())?;
self.write(r.label())?;
for f in r.fields() { self.write(f)?; }
self.write.close_record()
let mut c = self.write.start_record(r.arity() as u64)?;
let p = self.write(r.label())?;
self.write.extend_compound(&mut c, p)?;
for f in r.fields() {
let p = self.write(f)?;
self.write.extend_compound(&mut c, p)?;
}
self.write.end_compound(c)
}
Value::Sequence(ref vs) => {
self.write.open_sequence(vs.len())?;
for v in vs { self.write(v)?; }
self.write.close_sequence()
let mut c = self.write.start_sequence(vs.len() as u64)?;
for v in vs {
let p = self.write(v)?;
self.write.extend_compound(&mut c, p)?;
}
self.write.end_compound(c)
}
Value::Set(ref vs) => {
self.write.open_set(vs.len())?;
for v in vs { self.write(v)?; }
self.write.close_set()
let mut c = self.write.start_set(vs.len() as u64)?;
for v in vs {
let p = self.write(v)?;
self.write.extend_compound(&mut c, p)?;
}
self.write.end_compound(c)
}
Value::Dictionary(ref vs) => {
self.write.open_dictionary(vs.len())?;
for (k, v) in vs { self.write(k)?; self.write(v)?; }
self.write.close_dictionary()
let mut d = self.write.start_dictionary(vs.len() as u64)?;
for (k, v) in vs {
let p = self.write(k)?;
let kp = self.write.extend_dictionary_key(&mut d, p)?;
let p = self.write(v)?;
self.write.extend_dictionary_value(&mut d, kp, p)?;
}
self.write.end_dictionary(d)
}
Value::Domain(ref d) => self.write(&d.as_preserves()?)
}

View File

@ -1,20 +1,20 @@
pub mod constants;
pub mod de;
pub mod decoder;
pub mod encoder;
pub mod magic;
pub mod packed;
pub mod reader;
pub mod ser;
pub mod signed_integer;
pub mod value;
pub mod writer;
pub mod magic;
pub use de::Deserializer;
pub use de::from_value;
pub use decoder::Decoder;
pub use encoder::Encoder;
pub use reader::BinaryReader;
pub use packed::PackedReader;
pub use packed::PackedWriter;
pub use reader::Reader;
pub use ser::Serializer;
pub use ser::to_value;

View File

@ -0,0 +1,6 @@
pub mod constants;
pub mod reader;
pub mod writer;
pub use reader::PackedReader;
pub use writer::PackedWriter;

View File

@ -0,0 +1,574 @@
use num::bigint::BigInt;
use num::traits::cast::{FromPrimitive, ToPrimitive};
use std::borrow::Cow;
use std::convert::TryFrom;
use std::convert::TryInto;
// use std::io::{Read, Error};
use std::marker::PhantomData;
use super::super::signed_integer::SignedInteger;
use super::super::value::{Value, NestedValue, IOValue, FALSE, TRUE, Map, Set, Record, Annotations};
use super::constants::{Op, InvalidOp, AtomMinor, CompoundMinor};
use super::super::reader::{
BinarySource,
BytesBinarySource,
CompoundBody,
CompoundLimit,
IOBinarySource,
IOResult,
Reader,
ReaderResult,
};
use crate::error::{self, ExpectedKind, Received, is_eof_io_error, io_syntax_error};
pub struct PackedReader<'de, S: BinarySource<'de>> {
pub source: S,
phantom: PhantomData<&'de ()>,
}
impl<'de, S: BinarySource<'de>> BinarySource<'de> for PackedReader<'de, S> {
fn skip(&mut self) -> IOResult<()> {
self.source.skip()
}
fn peek(&mut self) -> IOResult<u8> {
self.source.peek()
}
fn readbytes(&mut self, count: usize) -> IOResult<Cow<'de, [u8]>> {
self.source.readbytes(count)
}
fn readbytes_into(&mut self, bs: &mut [u8]) -> IOResult<()> {
self.source.readbytes_into(bs)
}
}
fn out_of_range<I: Into<BigInt>>(i: I) -> error::Error {
error::Error::NumberOutOfRange(i.into())
}
impl<'de> PackedReader<'de, BytesBinarySource<'de>> {
pub fn from_bytes(bytes: &'de [u8]) -> Self {
PackedReader::new(BytesBinarySource::new(bytes))
}
}
impl<'de, 'a, IOR: std::io::Read> PackedReader<'de, IOBinarySource<'a, IOR>> {
pub fn from_read(read: &'a mut IOR) -> Self {
PackedReader::new(IOBinarySource::new(read))
}
}
impl<'de, S: BinarySource<'de>> PackedReader<'de, S> {
pub fn new(source: S) -> Self {
PackedReader { source, phantom: PhantomData }
}
fn read(&mut self) -> IOResult<u8> {
let v = self.peek()?;
self.skip()?;
Ok(v)
}
fn expected(&mut self, k: ExpectedKind) -> error::Error {
match self.demand_next(true) {
Ok(v) => error::Error::Expected(k, Received::ReceivedOtherValue(v)),
Err(e) => e.into()
}
}
fn varint(&mut self) -> IOResult<usize> {
let mut shift = 0;
let mut acc: usize = 0;
loop {
let v = self.read()?;
acc = acc | (((v & 0x7f) as usize) << shift);
shift = shift + 7;
if v & 0x80 == 0 { return Ok(acc) }
}
}
fn wirelength(&mut self, arg: u8) -> IOResult<usize> {
if arg < 15 {
Ok(usize::from(arg))
} else {
self.varint()
}
}
fn peekend(&mut self) -> IOResult<bool> {
if self.peek()? == 4 {
self.skip()?;
Ok(true)
} else {
Ok(false)
}
}
fn gather_chunks(&mut self) -> IOResult<Vec<u8>> {
let mut bs = Vec::with_capacity(256);
while !self.peekend()? {
match decodeop(self.peek()?)? {
(Op::Atom(AtomMinor::ByteString), arg) => {
self.skip()?;
let count = self.wirelength(arg)?;
if count == 0 {
return Err(io_syntax_error("Empty binary chunks are forbidden"));
}
bs.extend_from_slice(&self.readbytes(count)?)
},
_ => return Err(io_syntax_error("Unexpected non-format-B-ByteString chunk"))
}
}
Ok(bs)
}
fn peek_next_nonannotation_op(&mut self) -> ReaderResult<(Op, u8)> {
loop {
match decodeop(self.peek()?)? {
(Op::Misc(0), 5) => {
self.skip()?;
self.skip_value()?;
},
other => return Ok(other),
}
}
}
fn next_atomic(&mut self, minor: AtomMinor, k: ExpectedKind) -> ReaderResult<Cow<'de, [u8]>> {
match self.peek_next_nonannotation_op()? {
(Op::Atom(actual_minor), arg) if actual_minor == minor => {
self.skip()?;
let count = self.wirelength(arg)?;
Ok(self.readbytes(count)?)
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Atom(actual_minor) if actual_minor == minor => {
self.skip()?;
Ok(Cow::Owned(self.gather_chunks()?))
}
_ => Err(self.expected(k)),
},
_ => Err(self.expected(k)),
}
}
fn next_compound(&mut self, minor: CompoundMinor, k: ExpectedKind) ->
ReaderResult<CompoundBody<CompoundMinor>>
{
match self.peek_next_nonannotation_op()? {
(Op::Compound(actual_minor), arg) if actual_minor == minor => {
self.skip()?;
Ok(CompoundBody::counted(minor, self.wirelength(arg)?))
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Compound(actual_minor) if actual_minor == minor => {
self.skip()?;
Ok(CompoundBody::streaming(minor))
}
_ => Err(self.expected(k)),
},
_ => Err(self.expected(k)),
}
}
fn read_number_format_b(&mut self, count: usize) -> IOResult<SignedInteger> {
if count == 0 {
return Ok(SignedInteger::from(0 as i128));
}
if count > 16 {
let bs = self.readbytes(count)?;
if (bs[0] & 0x80) == 0 {
// Positive or zero.
let mut i = 0;
while i < count && bs[i] == 0 { i = i + 1; }
if count - i <= 16 {
Ok(SignedInteger::from(u128::from_be_bytes(bs[bs.len() - 16..].try_into().unwrap())))
} else {
Ok(SignedInteger::from(Cow::Owned(BigInt::from_bytes_be(num::bigint::Sign::Plus, &bs[i..]))))
}
} else {
// Negative.
let mut i = 0;
while i < count && bs[i] == 0xff { i = i + 1; }
if count - i <= 16 {
Ok(SignedInteger::from(i128::from_be_bytes(bs[bs.len() - 16..].try_into().unwrap())))
} else {
Ok(SignedInteger::from(Cow::Owned(BigInt::from_signed_bytes_be(&bs))))
}
}
} else {
let first_byte = self.read()?;
let prefix_byte = if (first_byte & 0x80) == 0 { 0x00 } else { 0xff };
let mut bs = [prefix_byte; 16];
bs[16 - count] = first_byte;
self.readbytes_into(&mut bs[16 - (count - 1)..])?;
Ok(SignedInteger::from(i128::from_be_bytes(bs)))
}
}
fn next_unsigned<T: FromPrimitive, F>(&mut self, f: F) -> ReaderResult<T>
where
F: FnOnce(u128) -> Option<T>
{
match self.peek_next_nonannotation_op()? {
(Op::Misc(3), arg) => {
self.skip()?;
if arg > 12 {
Err(out_of_range((arg as i8) - 16))
} else {
f(arg as u128).ok_or_else(|| out_of_range(arg))
}
}
(Op::Atom(AtomMinor::SignedInteger), arg) => {
self.skip()?;
let count = self.wirelength(arg)?;
let n = &self.read_number_format_b(count)?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
_ => {
let n_value = self.demand_next(false)?;
let n = n_value.value().to_signedinteger()?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
}
}
fn next_signed<T: FromPrimitive, F>(&mut self, f: F) -> ReaderResult<T>
where
F: FnOnce(i128) -> Option<T>
{
match self.peek_next_nonannotation_op()? {
(Op::Misc(3), arg) => {
self.skip()?;
let n = arg as i128;
let n = if n > 12 { n - 16 } else { n };
f(n).ok_or_else(|| out_of_range(n))
}
(Op::Atom(AtomMinor::SignedInteger), arg) => {
self.skip()?;
let count = self.wirelength(arg)?;
let n = &self.read_number_format_b(count)?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
_ => {
let n_value = self.demand_next(false)?;
let n = n_value.value().to_signedinteger()?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
}
}
}
impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
type CompoundInfo = CompoundMinor;
fn next(&mut self, read_annotations: bool) -> IOResult<Option<IOValue>> {
match self.peek() {
Err(e) if is_eof_io_error(&e) => return Ok(None),
Err(e) => return Err(e),
Ok(_) => (),
}
loop {
return Ok(Some(match decodeop(self.read()?)? {
(Op::Misc(0), 0) => FALSE.clone(),
(Op::Misc(0), 1) => TRUE.clone(),
(Op::Misc(0), 2) => {
let mut bs = [0; 4];
self.readbytes_into(&mut bs)?;
Value::from(f32::from_bits(u32::from_be_bytes(bs))).wrap()
}
(Op::Misc(0), 3) => {
let mut bs = [0; 8];
self.readbytes_into(&mut bs)?;
Value::from(f64::from_bits(u64::from_be_bytes(bs))).wrap()
}
(Op::Misc(0), 5) => {
if read_annotations {
let mut annotations = vec![self.demand_next(read_annotations)?];
while decodeop(self.peek()?)? == (Op::Misc(0), 5) {
self.skip()?;
annotations.push(self.demand_next(read_annotations)?);
}
let (existing_annotations, v) = self.demand_next(read_annotations)?.pieces();
annotations.extend_from_slice(existing_annotations.slice());
IOValue::wrap(Annotations::new(Some(annotations)), v)
} else {
self.skip_value()?;
continue;
}
}
(Op::Misc(0), _) => Err(io_syntax_error("Invalid format A encoding"))?,
(Op::Misc(1), _) => Err(io_syntax_error("Invalid format A encoding"))?,
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Atom(minor) =>
decodebinary(minor, Cow::Owned(self.gather_chunks()?))?,
Op::Compound(minor) => decodecompound(minor, DelimitedStream {
reader: ConfiguredPackedReader {
reader: self,
read_annotations,
phantom: PhantomData,
},
})?,
_ => Err(io_syntax_error("Invalid format C start byte"))?,
}
(Op::Misc(3), arg) => {
let n = if arg > 12 { i32::from(arg) - 16 } else { i32::from(arg) };
// TODO: prebuild these in value.rs
Value::from(n).wrap()
}
(Op::Misc(_), _) => unreachable!(),
(Op::Atom(AtomMinor::SignedInteger), arg) => {
let count = self.wirelength(arg)?;
let n = self.read_number_format_b(count)?;
Value::SignedInteger(n).wrap()
}
(Op::Atom(minor), arg) => {
let count = self.wirelength(arg)?;
decodebinary(minor, self.readbytes(count)?)?
}
(Op::Compound(minor), arg) => {
let count = self.wirelength(arg)?;
decodecompound(minor, CountedStream {
reader: ConfiguredPackedReader {
reader: self,
read_annotations,
phantom: PhantomData,
},
count,
})?
}
(Op::Reserved(3), 15) => continue,
(Op::Reserved(_), _) => return Err(InvalidOp.into()),
}))
}
}
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
if let Some(expected_arity) = arity {
let compound_format =
self.next_compound(CompoundMinor::Record, ExpectedKind::Record(arity))?;
if let CompoundLimit::Counted(count) = compound_format.limit {
if count != expected_arity + 1 /* we add 1 for the label */ {
return Err(error::Error::Expected(ExpectedKind::Record(arity),
Received::ReceivedSomethingElse));
}
}
Ok(compound_format)
} else {
self.next_compound(CompoundMinor::Record, ExpectedKind::Record(None))
}
}
fn open_sequence_or_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
match self.peek_next_nonannotation_op()? {
(Op::Compound(minor), arg)
if CompoundMinor::Sequence == minor || CompoundMinor::Set == minor => {
self.skip()?;
Ok(CompoundBody::counted(minor, self.wirelength(arg)?))
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Compound(minor)
if CompoundMinor::Sequence == minor || CompoundMinor::Set == minor => {
self.skip()?;
Ok(CompoundBody::streaming(minor))
}
_ => Err(self.expected(ExpectedKind::SequenceOrSet)),
}
_ => Err(self.expected(ExpectedKind::SequenceOrSet)),
}
}
fn open_sequence(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
self.next_compound(CompoundMinor::Sequence, ExpectedKind::Sequence)
}
fn open_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
self.next_compound(CompoundMinor::Set, ExpectedKind::Set)
}
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
self.next_compound(CompoundMinor::Dictionary, ExpectedKind::Dictionary)
}
fn close_compound_counted(&mut self, _minor: Self::CompoundInfo) -> ReaderResult<()> {
// Nothing to do -- no close delimiter to consume
Ok(())
}
fn close_compound_stream(&mut self, _minor: Self::CompoundInfo) -> ReaderResult<bool> {
Ok(self.peekend()?)
}
fn next_boolean(&mut self) -> ReaderResult<bool> {
match self.peek_next_nonannotation_op()? {
(Op::Misc(0), 0) => { self.skip()?; Ok(false) }
(Op::Misc(0), 1) => { self.skip()?; Ok(true) }
_ => Err(self.expected(ExpectedKind::Boolean)),
}
}
fn next_i8(&mut self) -> ReaderResult<i8> { self.next_signed(|n| n.to_i8()) }
fn next_i16(&mut self) -> ReaderResult<i16> { self.next_signed(|n| n.to_i16()) }
fn next_i32(&mut self) -> ReaderResult<i32> { self.next_signed(|n| n.to_i32()) }
fn next_i64(&mut self) -> ReaderResult<i64> { self.next_signed(|n| n.to_i64()) }
fn next_i128(&mut self) -> ReaderResult<i128> { self.next_signed(|n| n.to_i128()) }
fn next_u8(&mut self) -> ReaderResult<u8> { self.next_unsigned(|n| n.to_u8()) }
fn next_u16(&mut self) -> ReaderResult<u16> { self.next_unsigned(|n| n.to_u16()) }
fn next_u32(&mut self) -> ReaderResult<u32> { self.next_unsigned(|n| n.to_u32()) }
fn next_u64(&mut self) -> ReaderResult<u64> { self.next_unsigned(|n| n.to_u64()) }
fn next_u128(&mut self) -> ReaderResult<u128> { self.next_unsigned(|n| n.to_u128()) }
fn next_float(&mut self) -> ReaderResult<f32> {
match self.peek_next_nonannotation_op()? {
(Op::Misc(0), 2) => {
self.skip()?;
let mut bs = [0; 4];
self.readbytes_into(&mut bs)?;
Ok(f32::from_bits(u32::from_be_bytes(bs)))
},
(Op::Misc(0), 3) => {
self.skip()?;
let mut bs = [0; 8];
self.readbytes_into(&mut bs)?;
Ok(f64::from_bits(u64::from_be_bytes(bs)) as f32)
},
_ => Err(self.expected(ExpectedKind::Float)),
}
}
fn next_double(&mut self) -> ReaderResult<f64> {
match self.peek_next_nonannotation_op()? {
(Op::Misc(0), 2) => {
self.skip()?;
let mut bs = [0; 4];
self.readbytes_into(&mut bs)?;
Ok(f32::from_bits(u32::from_be_bytes(bs)) as f64)
},
(Op::Misc(0), 3) => {
self.skip()?;
let mut bs = [0; 8];
self.readbytes_into(&mut bs)?;
Ok(f64::from_bits(u64::from_be_bytes(bs)))
},
_ => Err(self.expected(ExpectedKind::Double)),
}
}
fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> {
Ok(decodestr(self.next_atomic(AtomMinor::String, ExpectedKind::Symbol)?)?)
}
fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
self.next_atomic(AtomMinor::ByteString, ExpectedKind::Symbol)
}
fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> {
Ok(decodestr(self.next_atomic(AtomMinor::Symbol, ExpectedKind::Symbol)?)?)
}
}
struct ConfiguredPackedReader<'de, 'a, S: BinarySource<'de>> {
reader: &'a mut PackedReader<'de, S>,
read_annotations: bool,
phantom: PhantomData<&'de ()>,
}
struct CountedStream<'de, 'a, S: BinarySource<'de>> {
reader: ConfiguredPackedReader<'de, 'a, S>,
count: usize,
}
impl<'de, 'a, S: BinarySource<'de>> Iterator for CountedStream<'de, 'a, S>
{
type Item = IOResult<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
if self.count == 0 { return None }
self.count -= 1;
Some(self.reader.reader.demand_next(self.reader.read_annotations))
}
}
struct DelimitedStream<'de, 'a, S: BinarySource<'de>> {
reader: ConfiguredPackedReader<'de, 'a, S>,
}
impl<'de, 'a, S: BinarySource<'de>> Iterator for DelimitedStream<'de, 'a, S>
{
type Item = IOResult<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.demand_next(self.reader.read_annotations)),
}
}
}
pub fn decodeop(b: u8) -> IOResult<(Op, u8)> {
Ok((Op::try_from(b >> 4)?, b & 15))
}
pub fn decodestr<'de>(cow: Cow<'de, [u8]>) -> IOResult<Cow<'de, str>> {
match cow {
Cow::Borrowed(bs) =>
Ok(Cow::Borrowed(std::str::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?)),
Cow::Owned(bs) =>
Ok(Cow::Owned(String::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?.to_owned())),
}
}
pub fn decodebinary<'de>(minor: AtomMinor, bs: Cow<'de, [u8]>) -> IOResult<IOValue> {
Ok(match minor {
AtomMinor::SignedInteger => Value::from(&BigInt::from_signed_bytes_be(&bs)).wrap(),
AtomMinor::String => Value::String(decodestr(bs)?.into_owned()).wrap(),
AtomMinor::ByteString => Value::ByteString(bs.into_owned()).wrap(),
AtomMinor::Symbol => Value::Symbol(decodestr(bs)?.into_owned()).wrap(),
})
}
pub fn decodecompound<'de, I: Iterator<Item = IOResult<IOValue>>>(
minor: CompoundMinor,
mut iter: I
) ->
IOResult<IOValue>
{
match minor {
CompoundMinor::Record => {
let vs = iter.collect::<IOResult<Vec<IOValue>>>()?;
if vs.len() < 1 {
Err(io_syntax_error("Too few elements in encoded record"))
} else {
Ok(Value::Record(Record(vs)).wrap())
}
}
CompoundMinor::Sequence => {
let vs = iter.collect::<IOResult<Vec<IOValue>>>()?;
Ok(Value::Sequence(vs).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(io_syntax_error("Missing dictionary value")),
}
}
Ok(Value::Dictionary(d).wrap())
}
}
}

View File

@ -0,0 +1,304 @@
use num;
use num::bigint::BigInt;
use num::cast::ToPrimitive;
use std::convert::TryInto;
use super::constants::{Op, AtomMinor, CompoundMinor};
use super::super::{Encoder, IOValue};
use super::super::writer::{Writer, Result, varint};
pub struct PackedWriter<'w, W: std::io::Write>(pub &'w mut W);
pub fn write_op<W: std::io::Write>(w: &mut PackedWriter<W>, op: Op, arg: u8) -> Result<()> {
w.0.write_all(&[(u8::from(op) << 4) | (arg & 15)])
}
pub fn write_header<W: std::io::Write>(w: &mut PackedWriter<W>, op: Op, wirelength: u64) -> Result<()> {
if wirelength < 15 {
write_op(w, op, wirelength as u8)
} else {
write_op(w, op, 15)?;
varint(w.0, wirelength)
}
}
pub fn write_atom<W: std::io::Write>(w: &mut PackedWriter<W>, minor: AtomMinor, bs: &[u8]) -> Result<()> {
write_header(w, Op::Atom(minor), bs.len() as u64)?;
w.0.write_all(bs)
}
macro_rules! fits_in_bytes {
($v:ident, $limit:literal) => ({
let bits = $limit * 8 - 1;
$v >= -(2 << bits) && $v < (2 << bits)
})
}
impl<'w, W: std::io::Write> PackedWriter<'w, W> {
pub fn write_noop(&mut self) -> Result<()> {
write_op(self, Op::Reserved(3), 15)
}
}
impl<'w, W: std::io::Write> Writer for PackedWriter<'w, W> {
type Pointer = ();
type Annotation = ();
type Compound = bool;
type Dictionary = bool;
type StreamedAtom = ();
type KeyPointer = ();
fn supports_streaming(&self) -> bool {
true
}
fn start_annotation(&mut self) -> Result<Self::Annotation> {
Ok(())
}
fn extend_annotation(&mut self, _a: &mut Self::Annotation, annotation: &IOValue) -> Result<()> {
write_header(self, Op::Misc(0), 5)?;
Encoder::new(self).write(annotation)
}
fn end_annotation(&mut self, _a: Self::Annotation, _value_p: Self::Pointer) -> Result<Self::Pointer> {
Ok(())
}
fn align(&mut self, _natural_chunksize: u64) -> Result<()> {
Ok(())
}
fn write_bool(&mut self, v: bool) -> Result<()> {
write_op(self, Op::Misc(0), if v { 1 } else { 0 })
}
fn write_f32(&mut self, v: f32) -> Result<()> {
write_op(self, Op::Misc(0), 2)?;
self.0.write_all(&u32::to_be_bytes(f32::to_bits(v)))
}
fn write_f64(&mut self, v: f64) -> Result<()> {
write_op(self, Op::Misc(0), 3)?;
self.0.write_all(&u64::to_be_bytes(f64::to_bits(v)))
}
fn write_i8(&mut self, v: i8) -> Result<()> {
if v >= 0 && v <= 12 { return write_op(self, Op::Misc(3), v as u8) }
if v >= -3 && v < 0 { return write_op(self, Op::Misc(3), (v + 16) as u8) }
write_atom(self, AtomMinor::SignedInteger, &[v as u8])
}
fn write_u8(&mut self, v: u8) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i8(w) }
write_atom(self, AtomMinor::SignedInteger, &[0, v])
}
fn write_i16(&mut self, v: i16) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i8(w) }
write_atom(self, AtomMinor::SignedInteger, &[(v >> 8) as u8, (v & 255) as u8])
}
fn write_u16(&mut self, v: u16) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i16(w) }
write_atom(self, AtomMinor::SignedInteger, &[0, (v >> 8) as u8, (v & 255) as u8])
}
fn write_i32(&mut self, v: i32) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i16(w) }
if fits_in_bytes!(v, 3) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_u32(&mut self, v: u32) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i32(w) }
return write_atom(self, AtomMinor::SignedInteger, &[0,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_i64(&mut self, v: i64) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i32(w) }
if fits_in_bytes!(v, 5) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
if fits_in_bytes!(v, 6) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
if fits_in_bytes!(v, 7) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 56) as u8,
(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_u64(&mut self, v: u64) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i64(w) }
return write_atom(self, AtomMinor::SignedInteger, &[0,
(v >> 56) as u8,
(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_i128(&mut self, v: i128) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i64(w) }
let bs: [u8; 16] = v.to_be_bytes();
if fits_in_bytes!(v, 9) { return write_atom(self, AtomMinor::SignedInteger, &bs[7..]); }
if fits_in_bytes!(v, 10) { return write_atom(self, AtomMinor::SignedInteger, &bs[6..]); }
if fits_in_bytes!(v, 11) { return write_atom(self, AtomMinor::SignedInteger, &bs[5..]); }
if fits_in_bytes!(v, 12) { return write_atom(self, AtomMinor::SignedInteger, &bs[4..]); }
if fits_in_bytes!(v, 13) { return write_atom(self, AtomMinor::SignedInteger, &bs[3..]); }
if fits_in_bytes!(v, 14) { return write_atom(self, AtomMinor::SignedInteger, &bs[2..]); }
if fits_in_bytes!(v, 15) { return write_atom(self, AtomMinor::SignedInteger, &bs[1..]); }
return write_atom(self, AtomMinor::SignedInteger, &bs);
}
fn write_u128(&mut self, v: u128) -> Result<()> {
if let Ok(w) = v.try_into() { return self.write_i128(w) }
let bs: [u8; 16] = v.to_be_bytes();
write_header(self, Op::Atom(AtomMinor::SignedInteger), (bs.len() + 1) as u64)?;
self.0.write_all(&[0])?;
self.0.write_all(&bs)
}
fn write_int(&mut self, v: &BigInt) -> Result<()> {
match v.to_i8() {
Some(n) => self.write_i8(n),
None => write_atom(self, AtomMinor::SignedInteger, &v.to_signed_bytes_be()),
}
}
fn write_string(&mut self, v: &str) -> Result<()> {
write_atom(self, AtomMinor::String, v.as_bytes())
}
fn write_bytes(&mut self, v: &[u8]) -> Result<()> {
write_atom(self, AtomMinor::ByteString, v)
}
fn write_symbol(&mut self, v: &str) -> Result<()> {
write_atom(self, AtomMinor::Symbol, v.as_bytes())
}
fn stream_string(&mut self) -> Result<Option<Self::StreamedAtom>> {
write_op(self, Op::Misc(2), Op::Atom(AtomMinor::String).into())?;
Ok(Some(()))
}
fn stream_bytes(&mut self) -> Result<Option<Self::StreamedAtom>> {
write_op(self, Op::Misc(2), Op::Atom(AtomMinor::ByteString).into())?;
Ok(Some(()))
}
fn stream_symbol(&mut self) -> Result<Option<Self::StreamedAtom>> {
write_op(self, Op::Misc(2), Op::Atom(AtomMinor::Symbol).into())?;
Ok(Some(()))
}
fn extend_atom(&mut self, _s: &mut Self::StreamedAtom, bs: &[u8]) -> Result<()> {
self.write_bytes(bs)
}
fn end_atom(&mut self, _s: Self::StreamedAtom) -> Result<()> {
write_op(self, Op::Misc(0), 4)
}
fn start_record(&mut self, field_count: u64) -> Result<Self::Compound> {
write_header(self, Op::Compound(CompoundMinor::Record), field_count + 1)?;
Ok(false)
}
fn start_sequence(&mut self, item_count: u64) -> Result<Self::Compound> {
write_header(self, Op::Compound(CompoundMinor::Sequence), item_count)?;
Ok(false)
}
fn start_set(&mut self, item_count: u64) -> Result<Self::Compound> {
write_header(self, Op::Compound(CompoundMinor::Set), item_count)?;
Ok(false)
}
fn stream_record(&mut self) -> Result<Option<Self::Compound>> {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Record).into())?;
Ok(Some(true))
}
fn stream_sequence(&mut self) -> Result<Option<Self::Compound>> {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Sequence).into())?;
Ok(Some(true))
}
fn stream_set(&mut self) -> Result<Option<Self::Compound>> {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Set).into())?;
Ok(Some(true))
}
fn extend_compound(&mut self, _s: &mut Self::Compound, _value_p: Self::Pointer) -> Result<()> {
Ok(())
}
fn end_compound(&mut self, s: Self::Compound) -> Result<()> {
if s {
write_op(self, Op::Misc(0), 4)
} else {
Ok(())
}
}
fn start_dictionary(&mut self, entry_count: u64) -> Result<Self::Dictionary> {
write_header(self, Op::Compound(CompoundMinor::Dictionary), entry_count << 1)?;
Ok(false)
}
fn stream_dictionary(&mut self) -> Result<Option<Self::Dictionary>> {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Dictionary).into())?;
Ok(Some(true))
}
fn extend_dictionary_key(&mut self, _s: &mut Self::Dictionary, _key_p: Self::Pointer) -> Result<Self::KeyPointer> {
Ok(())
}
fn extend_dictionary_value(&mut self, _s: &mut Self::Dictionary, _key_p: Self::KeyPointer, _value_p: Self::Pointer) -> Result<()> {
Ok(())
}
fn end_dictionary(&mut self, s: Self::Dictionary) -> Result<()> {
self.end_compound(s)
}
}

View File

@ -1,119 +1,22 @@
use num::bigint::BigInt;
use num::traits::cast::{FromPrimitive, ToPrimitive};
use std::borrow::Cow;
use std::convert::TryFrom;
use std::convert::TryInto;
use std::io::{Read, Error};
use std::marker::PhantomData;
use super::constants::{Op, InvalidOp, AtomMinor, CompoundMinor};
use super::signed_integer::SignedInteger;
use super::value::{Value, NestedValue, IOValue, FALSE, TRUE, Map, Set, Record, Annotations};
use crate::error::{self, ExpectedKind, Received, is_eof_io_error, io_eof, io_syntax_error};
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>;
#[derive(Debug)]
pub struct CompoundBody {
minor: CompoundMinor,
limit: CompoundLimit,
}
#[derive(Debug)]
pub enum CompoundLimit {
Counted(usize),
Streaming,
Finished,
}
impl CompoundBody {
pub fn counted(minor: CompoundMinor, size: usize) -> Self {
CompoundBody { minor, limit: CompoundLimit::Counted(size) }
}
pub fn streaming(minor: CompoundMinor) -> Self {
CompoundBody { minor, limit: CompoundLimit::Streaming }
}
pub fn more_expected<'de, R: Reader<'de>>(&mut self, read: &mut R) -> ReaderResult<bool> {
match self.limit {
CompoundLimit::Counted(ref mut n) =>
if *n == 0 {
read.close_compound_counted(self.minor)?;
self.limit = CompoundLimit::Finished;
Ok(false)
} else {
*n = *n - 1;
Ok(true)
},
CompoundLimit::Streaming =>
Ok(!read.close_compound_stream(self.minor)?),
CompoundLimit::Finished =>
Ok(false),
}
}
pub fn next_symbol<'de, R: Reader<'de>>(&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>>(&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>>(&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>>(&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>>(&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>>(&mut self, read: &mut R) -> ReaderResult<()> {
if self.more_expected(read)? {
Err(error::Error::MissingCloseDelimiter)
} else {
Ok(())
}
}
}
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>;
fn open_sequence_or_set(&mut self) -> ReaderResult<CompoundBody>;
fn open_sequence(&mut self) -> ReaderResult<CompoundBody>;
fn open_set(&mut self) -> ReaderResult<CompoundBody>;
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody>;
fn close_compound_counted(&mut self, minor: CompoundMinor) -> ReaderResult<()>;
fn close_compound_stream(&mut self, minor: CompoundMinor) -> ReaderResult<bool>;
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>;
//---------------------------------------------------------------------------
@ -158,7 +61,7 @@ pub trait Reader<'de> {
}
fn open_option(&mut self) ->
ReaderResult<(bool, CompoundBody)>
ReaderResult<(bool, CompoundBody<Self::CompoundInfo>)>
where
Self: Sized
{
@ -173,7 +76,7 @@ pub trait Reader<'de> {
}
fn open_simple_record(&mut self, name: &str, arity: Option<usize>) ->
ReaderResult<CompoundBody>
ReaderResult<CompoundBody<Self::CompoundInfo>>
where
Self: Sized
{
@ -189,36 +92,130 @@ pub trait Reader<'de> {
}
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> {
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> {
fn open_sequence_or_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
(*self).open_sequence_or_set()
}
fn open_sequence(&mut self) -> ReaderResult<CompoundBody> {
fn open_sequence(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
(*self).open_sequence()
}
fn open_set(&mut self) -> ReaderResult<CompoundBody> {
fn open_set(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
(*self).open_set()
}
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody> {
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody<Self::CompoundInfo>> {
(*self).open_dictionary()
}
fn close_compound_counted(&mut self, minor: CompoundMinor) -> ReaderResult<()> {
(*self).close_compound_counted(minor)
fn close_compound_counted(&mut self, info: Self::CompoundInfo) -> ReaderResult<()> {
(*self).close_compound_counted(info)
}
fn close_compound_stream(&mut self, minor: CompoundMinor) -> ReaderResult<bool> {
(*self).close_compound_stream(minor)
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(())
}
}
}
@ -324,552 +321,3 @@ impl<'de> BinarySource<'de> for BytesBinarySource<'de> {
}
}
}
pub struct BinaryReader<'de, S: BinarySource<'de>> {
pub source: S,
phantom: PhantomData<&'de ()>,
}
impl<'de, S: BinarySource<'de>> BinarySource<'de> for BinaryReader<'de, S> {
fn skip(&mut self) -> IOResult<()> {
self.source.skip()
}
fn peek(&mut self) -> IOResult<u8> {
self.source.peek()
}
fn readbytes(&mut self, count: usize) -> IOResult<Cow<'de, [u8]>> {
self.source.readbytes(count)
}
fn readbytes_into(&mut self, bs: &mut [u8]) -> IOResult<()> {
self.source.readbytes_into(bs)
}
}
pub fn from_bytes<'de>(bytes: &'de [u8]) ->
BinaryReader<'de, BytesBinarySource<'de>>
{
BinaryReader::new(BytesBinarySource::new(bytes))
}
pub fn from_read<'de, 'a, IOR: std::io::Read>(read: &'a mut IOR) ->
BinaryReader<'de, IOBinarySource<'a, IOR>>
{
BinaryReader::new(IOBinarySource::new(read))
}
fn out_of_range<I: Into<BigInt>>(i: I) -> error::Error {
error::Error::NumberOutOfRange(i.into())
}
impl<'de, S: BinarySource<'de>> BinaryReader<'de, S> {
pub fn new(source: S) -> Self {
BinaryReader { source, phantom: PhantomData }
}
fn read(&mut self) -> IOResult<u8> {
let v = self.peek()?;
self.skip()?;
Ok(v)
}
fn expected(&mut self, k: ExpectedKind) -> error::Error {
match self.demand_next(true) {
Ok(v) => error::Error::Expected(k, Received::ReceivedOtherValue(v)),
Err(e) => e.into()
}
}
fn varint(&mut self) -> IOResult<usize> {
let mut shift = 0;
let mut acc: usize = 0;
loop {
let v = self.read()?;
acc = acc | (((v & 0x7f) as usize) << shift);
shift = shift + 7;
if v & 0x80 == 0 { return Ok(acc) }
}
}
fn wirelength(&mut self, arg: u8) -> IOResult<usize> {
if arg < 15 {
Ok(usize::from(arg))
} else {
self.varint()
}
}
fn peekend(&mut self) -> IOResult<bool> {
if self.peek()? == 4 {
self.skip()?;
Ok(true)
} else {
Ok(false)
}
}
fn gather_chunks(&mut self) -> IOResult<Vec<u8>> {
let mut bs = Vec::with_capacity(256);
while !self.peekend()? {
match decodeop(self.peek()?)? {
(Op::Atom(AtomMinor::ByteString), arg) => {
self.skip()?;
let count = self.wirelength(arg)?;
if count == 0 {
return Err(io_syntax_error("Empty binary chunks are forbidden"));
}
bs.extend_from_slice(&self.readbytes(count)?)
},
_ => return Err(io_syntax_error("Unexpected non-format-B-ByteString chunk"))
}
}
Ok(bs)
}
fn peek_next_nonannotation_op(&mut self) -> ReaderResult<(Op, u8)> {
loop {
match decodeop(self.peek()?)? {
(Op::Misc(0), 5) => {
self.skip()?;
self.skip_value()?;
},
other => return Ok(other),
}
}
}
fn next_atomic(&mut self, minor: AtomMinor, k: ExpectedKind) -> ReaderResult<Cow<'de, [u8]>> {
match self.peek_next_nonannotation_op()? {
(Op::Atom(actual_minor), arg) if actual_minor == minor => {
self.skip()?;
let count = self.wirelength(arg)?;
Ok(self.readbytes(count)?)
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Atom(actual_minor) if actual_minor == minor => {
self.skip()?;
Ok(Cow::Owned(self.gather_chunks()?))
}
_ => Err(self.expected(k)),
},
_ => Err(self.expected(k)),
}
}
fn next_compound(&mut self, minor: CompoundMinor, k: ExpectedKind) ->
ReaderResult<CompoundBody>
{
match self.peek_next_nonannotation_op()? {
(Op::Compound(actual_minor), arg) if actual_minor == minor => {
self.skip()?;
Ok(CompoundBody::counted(minor, self.wirelength(arg)?))
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Compound(actual_minor) if actual_minor == minor => {
self.skip()?;
Ok(CompoundBody::streaming(minor))
}
_ => Err(self.expected(k)),
},
_ => Err(self.expected(k)),
}
}
fn read_number_format_b(&mut self, count: usize) -> IOResult<SignedInteger> {
if count == 0 {
return Ok(SignedInteger::from(0 as i128));
}
if count > 16 {
let bs = self.readbytes(count)?;
if (bs[0] & 0x80) == 0 {
// Positive or zero.
let mut i = 0;
while i < count && bs[i] == 0 { i = i + 1; }
if count - i <= 16 {
Ok(SignedInteger::from(u128::from_be_bytes(bs[bs.len() - 16..].try_into().unwrap())))
} else {
Ok(SignedInteger::from(Cow::Owned(BigInt::from_bytes_be(num::bigint::Sign::Plus, &bs[i..]))))
}
} else {
// Negative.
let mut i = 0;
while i < count && bs[i] == 0xff { i = i + 1; }
if count - i <= 16 {
Ok(SignedInteger::from(i128::from_be_bytes(bs[bs.len() - 16..].try_into().unwrap())))
} else {
Ok(SignedInteger::from(Cow::Owned(BigInt::from_signed_bytes_be(&bs))))
}
}
} else {
let first_byte = self.read()?;
let prefix_byte = if (first_byte & 0x80) == 0 { 0x00 } else { 0xff };
let mut bs = [prefix_byte; 16];
bs[16 - count] = first_byte;
self.readbytes_into(&mut bs[16 - (count - 1)..])?;
Ok(SignedInteger::from(i128::from_be_bytes(bs)))
}
}
fn next_unsigned<T: FromPrimitive, F>(&mut self, f: F) -> ReaderResult<T>
where
F: FnOnce(u128) -> Option<T>
{
match self.peek_next_nonannotation_op()? {
(Op::Misc(3), arg) => {
self.skip()?;
if arg > 12 {
Err(out_of_range((arg as i8) - 16))
} else {
f(arg as u128).ok_or_else(|| out_of_range(arg))
}
}
(Op::Atom(AtomMinor::SignedInteger), arg) => {
self.skip()?;
let count = self.wirelength(arg)?;
let n = &self.read_number_format_b(count)?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
_ => {
let n_value = self.demand_next(false)?;
let n = n_value.value().to_signedinteger()?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
}
}
fn next_signed<T: FromPrimitive, F>(&mut self, f: F) -> ReaderResult<T>
where
F: FnOnce(i128) -> Option<T>
{
match self.peek_next_nonannotation_op()? {
(Op::Misc(3), arg) => {
self.skip()?;
let n = arg as i128;
let n = if n > 12 { n - 16 } else { n };
f(n).ok_or_else(|| out_of_range(n))
}
(Op::Atom(AtomMinor::SignedInteger), arg) => {
self.skip()?;
let count = self.wirelength(arg)?;
let n = &self.read_number_format_b(count)?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
_ => {
let n_value = self.demand_next(false)?;
let n = n_value.value().to_signedinteger()?;
let i = n.try_into().or_else(|_| Err(out_of_range(n)))?;
f(i).ok_or_else(|| out_of_range(i))
}
}
}
}
impl<'de, S: BinarySource<'de>> Reader<'de> for BinaryReader<'de, S> {
fn next(&mut self, read_annotations: bool) -> IOResult<Option<IOValue>> {
match self.peek() {
Err(e) if is_eof_io_error(&e) => return Ok(None),
Err(e) => return Err(e),
Ok(_) => (),
}
loop {
return Ok(Some(match decodeop(self.read()?)? {
(Op::Misc(0), 0) => FALSE.clone(),
(Op::Misc(0), 1) => TRUE.clone(),
(Op::Misc(0), 2) => {
let mut bs = [0; 4];
self.readbytes_into(&mut bs)?;
Value::from(f32::from_bits(u32::from_be_bytes(bs))).wrap()
}
(Op::Misc(0), 3) => {
let mut bs = [0; 8];
self.readbytes_into(&mut bs)?;
Value::from(f64::from_bits(u64::from_be_bytes(bs))).wrap()
}
(Op::Misc(0), 5) => {
if read_annotations {
let mut annotations = vec![self.demand_next(read_annotations)?];
while decodeop(self.peek()?)? == (Op::Misc(0), 5) {
self.skip()?;
annotations.push(self.demand_next(read_annotations)?);
}
let (existing_annotations, v) = self.demand_next(read_annotations)?.pieces();
annotations.extend_from_slice(existing_annotations.slice());
IOValue::wrap(Annotations::new(Some(annotations)), v)
} else {
self.skip_value()?;
continue;
}
}
(Op::Misc(0), _) => Err(io_syntax_error("Invalid format A encoding"))?,
(Op::Misc(1), _) => Err(io_syntax_error("Invalid format A encoding"))?,
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Atom(minor) =>
decodebinary(minor, Cow::Owned(self.gather_chunks()?))?,
Op::Compound(minor) => decodecompound(minor, DelimitedStream {
reader: ConfiguredBinaryReader {
reader: self,
read_annotations,
phantom: PhantomData,
},
})?,
_ => Err(io_syntax_error("Invalid format C start byte"))?,
}
(Op::Misc(3), arg) => {
let n = if arg > 12 { i32::from(arg) - 16 } else { i32::from(arg) };
// TODO: prebuild these in value.rs
Value::from(n).wrap()
}
(Op::Misc(_), _) => unreachable!(),
(Op::Atom(AtomMinor::SignedInteger), arg) => {
let count = self.wirelength(arg)?;
let n = self.read_number_format_b(count)?;
Value::SignedInteger(n).wrap()
}
(Op::Atom(minor), arg) => {
let count = self.wirelength(arg)?;
decodebinary(minor, self.readbytes(count)?)?
}
(Op::Compound(minor), arg) => {
let count = self.wirelength(arg)?;
decodecompound(minor, CountedStream {
reader: ConfiguredBinaryReader {
reader: self,
read_annotations,
phantom: PhantomData,
},
count,
})?
}
(Op::Reserved(3), 15) => continue,
(Op::Reserved(_), _) => return Err(InvalidOp.into()),
}))
}
}
fn open_record(&mut self, arity: Option<usize>) -> ReaderResult<CompoundBody> {
if let Some(expected_arity) = arity {
let compound_format =
self.next_compound(CompoundMinor::Record, ExpectedKind::Record(arity))?;
if let CompoundLimit::Counted(count) = compound_format.limit {
if count != expected_arity + 1 /* we add 1 for the label */ {
return Err(error::Error::Expected(ExpectedKind::Record(arity),
Received::ReceivedSomethingElse));
}
}
Ok(compound_format)
} else {
self.next_compound(CompoundMinor::Record, ExpectedKind::Record(None))
}
}
fn open_sequence_or_set(&mut self) -> ReaderResult<CompoundBody> {
match self.peek_next_nonannotation_op()? {
(Op::Compound(minor), arg)
if CompoundMinor::Sequence == minor || CompoundMinor::Set == minor => {
self.skip()?;
Ok(CompoundBody::counted(minor, self.wirelength(arg)?))
}
(Op::Misc(2), arg) => match Op::try_from(arg)? {
Op::Compound(minor)
if CompoundMinor::Sequence == minor || CompoundMinor::Set == minor => {
self.skip()?;
Ok(CompoundBody::streaming(minor))
}
_ => Err(self.expected(ExpectedKind::SequenceOrSet)),
}
_ => Err(self.expected(ExpectedKind::SequenceOrSet)),
}
}
fn open_sequence(&mut self) -> ReaderResult<CompoundBody> {
self.next_compound(CompoundMinor::Sequence, ExpectedKind::Sequence)
}
fn open_set(&mut self) -> ReaderResult<CompoundBody> {
self.next_compound(CompoundMinor::Set, ExpectedKind::Set)
}
fn open_dictionary(&mut self) -> ReaderResult<CompoundBody> {
self.next_compound(CompoundMinor::Dictionary, ExpectedKind::Dictionary)
}
fn close_compound_counted(&mut self, _minor: CompoundMinor) -> ReaderResult<()> {
// Nothing to do -- no close delimiter to consume
Ok(())
}
fn close_compound_stream(&mut self, _minor: CompoundMinor) -> ReaderResult<bool> {
Ok(self.peekend()?)
}
fn next_boolean(&mut self) -> ReaderResult<bool> {
match self.peek_next_nonannotation_op()? {
(Op::Misc(0), 0) => { self.skip()?; Ok(false) }
(Op::Misc(0), 1) => { self.skip()?; Ok(true) }
_ => Err(self.expected(ExpectedKind::Boolean)),
}
}
fn next_i8(&mut self) -> ReaderResult<i8> { self.next_signed(|n| n.to_i8()) }
fn next_i16(&mut self) -> ReaderResult<i16> { self.next_signed(|n| n.to_i16()) }
fn next_i32(&mut self) -> ReaderResult<i32> { self.next_signed(|n| n.to_i32()) }
fn next_i64(&mut self) -> ReaderResult<i64> { self.next_signed(|n| n.to_i64()) }
fn next_i128(&mut self) -> ReaderResult<i128> { self.next_signed(|n| n.to_i128()) }
fn next_u8(&mut self) -> ReaderResult<u8> { self.next_unsigned(|n| n.to_u8()) }
fn next_u16(&mut self) -> ReaderResult<u16> { self.next_unsigned(|n| n.to_u16()) }
fn next_u32(&mut self) -> ReaderResult<u32> { self.next_unsigned(|n| n.to_u32()) }
fn next_u64(&mut self) -> ReaderResult<u64> { self.next_unsigned(|n| n.to_u64()) }
fn next_u128(&mut self) -> ReaderResult<u128> { self.next_unsigned(|n| n.to_u128()) }
fn next_float(&mut self) -> ReaderResult<f32> {
match self.peek_next_nonannotation_op()? {
(Op::Misc(0), 2) => {
self.skip()?;
let mut bs = [0; 4];
self.readbytes_into(&mut bs)?;
Ok(f32::from_bits(u32::from_be_bytes(bs)))
},
(Op::Misc(0), 3) => {
self.skip()?;
let mut bs = [0; 8];
self.readbytes_into(&mut bs)?;
Ok(f64::from_bits(u64::from_be_bytes(bs)) as f32)
},
_ => Err(self.expected(ExpectedKind::Float)),
}
}
fn next_double(&mut self) -> ReaderResult<f64> {
match self.peek_next_nonannotation_op()? {
(Op::Misc(0), 2) => {
self.skip()?;
let mut bs = [0; 4];
self.readbytes_into(&mut bs)?;
Ok(f32::from_bits(u32::from_be_bytes(bs)) as f64)
},
(Op::Misc(0), 3) => {
self.skip()?;
let mut bs = [0; 8];
self.readbytes_into(&mut bs)?;
Ok(f64::from_bits(u64::from_be_bytes(bs)))
},
_ => Err(self.expected(ExpectedKind::Double)),
}
}
fn next_str(&mut self) -> ReaderResult<Cow<'de, str>> {
Ok(decodestr(self.next_atomic(AtomMinor::String, ExpectedKind::Symbol)?)?)
}
fn next_bytestring(&mut self) -> ReaderResult<Cow<'de, [u8]>> {
self.next_atomic(AtomMinor::ByteString, ExpectedKind::Symbol)
}
fn next_symbol(&mut self) -> ReaderResult<Cow<'de, str>> {
Ok(decodestr(self.next_atomic(AtomMinor::Symbol, ExpectedKind::Symbol)?)?)
}
}
struct ConfiguredBinaryReader<'de, 'a, S: BinarySource<'de>> {
reader: &'a mut BinaryReader<'de, S>,
read_annotations: bool,
phantom: PhantomData<&'de ()>,
}
struct CountedStream<'de, 'a, S: BinarySource<'de>> {
reader: ConfiguredBinaryReader<'de, 'a, S>,
count: usize,
}
impl<'de, 'a, S: BinarySource<'de>> Iterator for CountedStream<'de, 'a, S>
{
type Item = IOResult<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
if self.count == 0 { return None }
self.count -= 1;
Some(self.reader.reader.demand_next(self.reader.read_annotations))
}
}
struct DelimitedStream<'de, 'a, S: BinarySource<'de>> {
reader: ConfiguredBinaryReader<'de, 'a, S>,
}
impl<'de, 'a, S: BinarySource<'de>> Iterator for DelimitedStream<'de, 'a, S>
{
type Item = IOResult<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.demand_next(self.reader.read_annotations)),
}
}
}
pub fn decodeop(b: u8) -> IOResult<(Op, u8)> {
Ok((Op::try_from(b >> 4)?, b & 15))
}
pub fn decodestr<'de>(cow: Cow<'de, [u8]>) -> IOResult<Cow<'de, str>> {
match cow {
Cow::Borrowed(bs) =>
Ok(Cow::Borrowed(std::str::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?)),
Cow::Owned(bs) =>
Ok(Cow::Owned(String::from_utf8(bs).map_err(|_| io_syntax_error("Invalid UTF-8"))?.to_owned())),
}
}
pub fn decodebinary<'de>(minor: AtomMinor, bs: Cow<'de, [u8]>) -> IOResult<IOValue> {
Ok(match minor {
AtomMinor::SignedInteger => Value::from(&BigInt::from_signed_bytes_be(&bs)).wrap(),
AtomMinor::String => Value::String(decodestr(bs)?.into_owned()).wrap(),
AtomMinor::ByteString => Value::ByteString(bs.into_owned()).wrap(),
AtomMinor::Symbol => Value::Symbol(decodestr(bs)?.into_owned()).wrap(),
})
}
pub fn decodecompound<'de, I: Iterator<Item = IOResult<IOValue>>>(
minor: CompoundMinor,
mut iter: I
) ->
IOResult<IOValue>
{
match minor {
CompoundMinor::Record => {
let vs = iter.collect::<IOResult<Vec<IOValue>>>()?;
if vs.len() < 1 {
Err(io_syntax_error("Too few elements in encoded record"))
} else {
Ok(Value::Record(Record(vs)).wrap())
}
}
CompoundMinor::Sequence => {
let vs = iter.collect::<IOResult<Vec<IOValue>>>()?;
Ok(Value::Sequence(vs).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(io_syntax_error("Missing dictionary value")),
}
}
Ok(Value::Dictionary(d).wrap())
}
}
}

View File

@ -1,60 +1,81 @@
use num;
use num::bigint::BigInt;
use num::cast::ToPrimitive;
use std::convert::TryInto;
use std::io::Error;
use super::constants::{Op, AtomMinor, CompoundMinor};
use super::value::IOValue;
pub type Result = std::result::Result<(), Error>;
pub type Result<T> = std::result::Result<T, Error>;
pub trait Writer {
fn write_annotation_prefix(&mut self) -> Result;
fn write_noop(&mut self) -> Result;
type Pointer;
type Annotation;
type Compound;
type Dictionary;
type StreamedAtom;
type KeyPointer;
fn write_bool(&mut self, v: bool) -> Result;
fn supports_streaming(&self) -> bool;
fn write_f32(&mut self, v: f32) -> Result;
fn write_f64(&mut self, v: f64) -> Result;
fn align(&mut self, natural_chunksize: u64) -> Result<()>;
fn write_i8(&mut self, v: i8) -> Result;
fn write_u8(&mut self, v: u8) -> Result;
fn write_i16(&mut self, v: i16) -> Result;
fn write_u16(&mut self, v: u16) -> Result;
fn write_i32(&mut self, v: i32) -> Result;
fn write_u32(&mut self, v: u32) -> Result;
fn write_i64(&mut self, v: i64) -> Result;
fn write_u64(&mut self, v: u64) -> Result;
fn write_i128(&mut self, v: i128) -> Result;
fn write_u128(&mut self, v: u128) -> Result;
fn write_int(&mut self, v: &BigInt) -> Result;
fn start_annotation(&mut self) -> Result<Self::Annotation>;
fn extend_annotation(&mut self, a: &mut Self::Annotation, annotation: &IOValue) -> Result<()>;
fn end_annotation(&mut self, a: Self::Annotation, value_p: Self::Pointer) -> Result<Self::Pointer>;
fn write_string(&mut self, v: &str) -> Result;
fn write_bytes(&mut self, v: &[u8]) -> Result;
fn write_symbol(&mut self, v: &str) -> Result;
fn write_bool(&mut self, v: bool) -> Result<Self::Pointer>;
fn open_record(&mut self, field_count: usize) -> Result;
fn open_sequence(&mut self, item_count: usize) -> Result;
fn open_set(&mut self, item_count: usize) -> Result;
fn open_dictionary(&mut self, entry_count: usize) -> Result;
fn write_f32(&mut self, v: f32) -> Result<Self::Pointer>;
fn write_f64(&mut self, v: f64) -> Result<Self::Pointer>;
fn close_record(&mut self) -> Result;
fn close_sequence(&mut self) -> Result;
fn close_set(&mut self) -> Result;
fn close_dictionary(&mut self) -> Result;
fn write_i8(&mut self, v: i8) -> Result<Self::Pointer>;
fn write_u8(&mut self, v: u8) -> Result<Self::Pointer>;
fn write_i16(&mut self, v: i16) -> Result<Self::Pointer>;
fn write_u16(&mut self, v: u16) -> Result<Self::Pointer>;
fn write_i32(&mut self, v: i32) -> Result<Self::Pointer>;
fn write_u32(&mut self, v: u32) -> Result<Self::Pointer>;
fn write_i64(&mut self, v: i64) -> Result<Self::Pointer>;
fn write_u64(&mut self, v: u64) -> Result<Self::Pointer>;
fn write_i128(&mut self, v: i128) -> Result<Self::Pointer>;
fn write_u128(&mut self, v: u128) -> Result<Self::Pointer>;
fn write_int(&mut self, v: &BigInt) -> Result<Self::Pointer>;
fn stream_string(&mut self) -> Result;
fn stream_bytes(&mut self) -> Result;
fn stream_symbol(&mut self) -> Result;
fn write_string(&mut self, v: &str) -> Result<Self::Pointer>;
fn write_bytes(&mut self, v: &[u8]) -> Result<Self::Pointer>;
fn write_symbol(&mut self, v: &str) -> Result<Self::Pointer>;
fn stream_record(&mut self) -> Result;
fn stream_sequence(&mut self) -> Result;
fn stream_set(&mut self) -> Result;
fn stream_dictionary(&mut self) -> Result;
fn stream_string(&mut self) -> Result<Option<Self::StreamedAtom>>;
fn stream_bytes(&mut self) -> Result<Option<Self::StreamedAtom>>;
fn stream_symbol(&mut self) -> Result<Option<Self::StreamedAtom>>;
fn extend_atom(&mut self, s: &mut Self::StreamedAtom, bs: &[u8]) -> Result<()>;
fn end_atom(&mut self, s: Self::StreamedAtom) -> Result<Self::Pointer>;
fn close_stream(&mut self) -> Result;
fn start_record(&mut self, field_count: u64) -> Result<Self::Compound>;
fn start_sequence(&mut self, item_count: u64) -> Result<Self::Compound>;
fn start_set(&mut self, item_count: u64) -> Result<Self::Compound>;
fn stream_record(&mut self) -> Result<Option<Self::Compound>>;
fn stream_sequence(&mut self) -> Result<Option<Self::Compound>>;
fn stream_set(&mut self) -> Result<Option<Self::Compound>>;
fn extend_compound(&mut self, s: &mut Self::Compound, value_p: Self::Pointer) -> Result<()>;
fn end_compound(&mut self, s: Self::Compound) -> Result<Self::Pointer>;
fn start_dictionary(&mut self, entry_count: u64) -> Result<Self::Dictionary>;
fn stream_dictionary(&mut self) -> Result<Option<Self::Dictionary>>;
fn extend_dictionary_key(&mut self, s: &mut Self::Dictionary, key_p: Self::Pointer) -> Result<Self::KeyPointer>;
fn extend_dictionary_value(&mut self, s: &mut Self::Dictionary, key_p: Self::KeyPointer, value_p: Self::Pointer) -> Result<()>;
fn end_dictionary(&mut self, s: Self::Dictionary) -> Result<Self::Pointer>;
}
pub fn varint<W: std::io::Write>(w: &mut W, mut v: usize) -> Result {
pub fn bigvarint<W: std::io::Write>(w: &mut W, mut v: u64) -> Result<()> {
loop {
if v < (2 << 31) {
return w.write_all(&(v as u32).to_le_bytes());
} else {
w.write_all(&(((v & 0x7fffffff) + (2 << 31)) as u32).to_le_bytes())?;
v = v >> 31;
}
}
}
pub fn varint<W: std::io::Write>(w: &mut W, mut v: u64) -> Result<()> {
loop {
if v < 128 {
return w.write_all(&[v as u8])
@ -64,237 +85,3 @@ pub fn varint<W: std::io::Write>(w: &mut W, mut v: usize) -> Result {
}
}
}
pub fn write_op<W: std::io::Write>(w: &mut W, op: Op, arg: u8) -> Result {
w.write_all(&[(u8::from(op) << 4) | (arg & 15)])
}
pub fn write_header<W: std::io::Write>(w: &mut W, op: Op, wirelength: usize) -> Result {
if wirelength < 15 {
write_op(w, op, wirelength as u8)
} else {
write_op(w, op, 15)?;
varint(w, wirelength)
}
}
pub fn write_atom<W: std::io::Write>(w: &mut W, minor: AtomMinor, bs: &[u8]) -> Result {
write_header(w, Op::Atom(minor), bs.len())?;
w.write_all(bs)
}
macro_rules! fits_in_bytes {
($v:ident, $limit:literal) => ({
let bits = $limit * 8 - 1;
$v >= -(2 << bits) && $v < (2 << bits)
})
}
impl<W: std::io::Write> Writer for W {
fn write_annotation_prefix(&mut self) -> Result {
write_header(self, Op::Misc(0), 5)
}
fn write_noop(&mut self) -> Result {
write_op(self, Op::Reserved(3), 15)
}
fn write_bool(&mut self, v: bool) -> Result {
write_op(self, Op::Misc(0), if v { 1 } else { 0 })
}
fn write_f32(&mut self, v: f32) -> Result {
write_op(self, Op::Misc(0), 2)?;
self.write_all(&u32::to_be_bytes(f32::to_bits(v)))
}
fn write_f64(&mut self, v: f64) -> Result {
write_op(self, Op::Misc(0), 3)?;
self.write_all(&u64::to_be_bytes(f64::to_bits(v)))
}
fn write_i8(&mut self, v: i8) -> Result {
if v >= 0 && v <= 12 { return write_op(self, Op::Misc(3), v as u8) }
if v >= -3 && v < 0 { return write_op(self, Op::Misc(3), (v + 16) as u8) }
write_atom(self, AtomMinor::SignedInteger, &[v as u8])
}
fn write_u8(&mut self, v: u8) -> Result {
if let Ok(w) = v.try_into() { return self.write_i8(w) }
write_atom(self, AtomMinor::SignedInteger, &[0, v])
}
fn write_i16(&mut self, v: i16) -> Result {
if let Ok(w) = v.try_into() { return self.write_i8(w) }
write_atom(self, AtomMinor::SignedInteger, &[(v >> 8) as u8, (v & 255) as u8])
}
fn write_u16(&mut self, v: u16) -> Result {
if let Ok(w) = v.try_into() { return self.write_i16(w) }
write_atom(self, AtomMinor::SignedInteger, &[0, (v >> 8) as u8, (v & 255) as u8])
}
fn write_i32(&mut self, v: i32) -> Result {
if let Ok(w) = v.try_into() { return self.write_i16(w) }
if fits_in_bytes!(v, 3) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_u32(&mut self, v: u32) -> Result {
if let Ok(w) = v.try_into() { return self.write_i32(w) }
return write_atom(self, AtomMinor::SignedInteger, &[0,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_i64(&mut self, v: i64) -> Result {
if let Ok(w) = v.try_into() { return self.write_i32(w) }
if fits_in_bytes!(v, 5) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
if fits_in_bytes!(v, 6) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
if fits_in_bytes!(v, 7) {
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
return write_atom(self, AtomMinor::SignedInteger, &[(v >> 56) as u8,
(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_u64(&mut self, v: u64) -> Result {
if let Ok(w) = v.try_into() { return self.write_i64(w) }
return write_atom(self, AtomMinor::SignedInteger, &[0,
(v >> 56) as u8,
(v >> 48) as u8,
(v >> 40) as u8,
(v >> 32) as u8,
(v >> 24) as u8,
(v >> 16) as u8,
(v >> 8) as u8,
(v & 255) as u8]);
}
fn write_i128(&mut self, v: i128) -> Result {
if let Ok(w) = v.try_into() { return self.write_i64(w) }
let bs: [u8; 16] = v.to_be_bytes();
if fits_in_bytes!(v, 9) { return write_atom(self, AtomMinor::SignedInteger, &bs[7..]); }
if fits_in_bytes!(v, 10) { return write_atom(self, AtomMinor::SignedInteger, &bs[6..]); }
if fits_in_bytes!(v, 11) { return write_atom(self, AtomMinor::SignedInteger, &bs[5..]); }
if fits_in_bytes!(v, 12) { return write_atom(self, AtomMinor::SignedInteger, &bs[4..]); }
if fits_in_bytes!(v, 13) { return write_atom(self, AtomMinor::SignedInteger, &bs[3..]); }
if fits_in_bytes!(v, 14) { return write_atom(self, AtomMinor::SignedInteger, &bs[2..]); }
if fits_in_bytes!(v, 15) { return write_atom(self, AtomMinor::SignedInteger, &bs[1..]); }
return write_atom(self, AtomMinor::SignedInteger, &bs);
}
fn write_u128(&mut self, v: u128) -> Result {
if let Ok(w) = v.try_into() { return self.write_i128(w) }
let bs: [u8; 16] = v.to_be_bytes();
write_header(self, Op::Atom(AtomMinor::SignedInteger), bs.len() + 1)?;
self.write_all(&[0])?;
self.write_all(&bs)
}
fn write_int(&mut self, v: &BigInt) -> Result {
match v.to_i8() {
Some(n) => self.write_i8(n),
None => write_atom(self, AtomMinor::SignedInteger, &v.to_signed_bytes_be()),
}
}
fn write_string(&mut self, v: &str) -> Result {
write_atom(self, AtomMinor::String, v.as_bytes())
}
fn write_bytes(&mut self, v: &[u8]) -> Result {
write_atom(self, AtomMinor::ByteString, v)
}
fn write_symbol(&mut self, v: &str) -> Result {
write_atom(self, AtomMinor::Symbol, v.as_bytes())
}
fn open_record(&mut self, field_count: usize) -> Result {
write_header(self, Op::Compound(CompoundMinor::Record), field_count + 1)
}
fn open_sequence(&mut self, item_count: usize) -> Result {
write_header(self, Op::Compound(CompoundMinor::Sequence), item_count)
}
fn open_set(&mut self, item_count: usize) -> Result {
write_header(self, Op::Compound(CompoundMinor::Set), item_count)
}
fn open_dictionary(&mut self, entry_count: usize) -> Result {
write_header(self, Op::Compound(CompoundMinor::Dictionary), entry_count << 1)
}
fn close_record(&mut self) -> Result { Ok(()) }
fn close_sequence(&mut self) -> Result { Ok(()) }
fn close_set(&mut self) -> Result { Ok(()) }
fn close_dictionary(&mut self) -> Result { Ok(()) }
fn stream_string(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Atom(AtomMinor::String).into())
}
fn stream_bytes(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Atom(AtomMinor::ByteString).into())
}
fn stream_symbol(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Atom(AtomMinor::Symbol).into())
}
fn stream_record(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Record).into())
}
fn stream_sequence(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Sequence).into())
}
fn stream_set(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Set).into())
}
fn stream_dictionary(&mut self) -> Result {
write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Dictionary).into())
}
fn close_stream(&mut self) -> Result {
write_op(self, Op::Misc(0), 4)
}
}