Refactor to extract packed format from general traits. Regression in encode performance?
This commit is contained in:
parent
3f76049f13
commit
28101cc7d1
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ pub enum Error {
|
|||
MissingCloseDelimiter,
|
||||
MissingItem,
|
||||
Expected(ExpectedKind, Received),
|
||||
StreamingSerializationUnsupported,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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()?)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
pub mod constants;
|
||||
pub mod reader;
|
||||
pub mod writer;
|
||||
|
||||
pub use reader::PackedReader;
|
||||
pub use writer::PackedWriter;
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue