diff --git a/implementations/rust/benches/codec.rs b/implementations/rust/benches/codec.rs index 0606ef9..cce8825 100644 --- a/implementations/rust/benches/codec.rs +++ b/implementations/rust/benches/codec.rs @@ -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(); } diff --git a/implementations/rust/src/de.rs b/implementations/rust/src/de.rs index 6a32037..5968895 100644 --- a/implementations/rust/src/de.rs +++ b/implementations/rust/src/de.rs @@ -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, } 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) -> Self { Seq { de, compound_body } } diff --git a/implementations/rust/src/error.rs b/implementations/rust/src/error.rs index bf74a06..54ac674 100644 --- a/implementations/rust/src/error.rs +++ b/implementations/rust/src/error.rs @@ -12,6 +12,7 @@ pub enum Error { MissingCloseDelimiter, MissingItem, Expected(ExpectedKind, Received), + StreamingSerializationUnsupported, } #[derive(Debug)] diff --git a/implementations/rust/src/lib.rs b/implementations/rust/src/lib.rs index afc2dff..25bce45 100644 --- a/implementations/rust/src/lib.rs +++ b/implementations/rust/src/lib.rs @@ -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); diff --git a/implementations/rust/src/ser.rs b/implementations/rust/src/ser.rs index 9a920de..c03ec73 100644 --- a/implementations/rust/src/ser.rs +++ b/implementations/rust/src/ser.rs @@ -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, + c: W::Compound, +} + +#[derive(Debug)] +pub struct SerializeDictionary<'a, 'b, W: Writer> { + ser: &'a mut Serializer<'b, W>, + d: W::Dictionary, + key_p: Option, } 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 { Ok(self.write.write_bool(v)?) } - fn serialize_i8(self, v: i8) -> Result<()> { + fn serialize_i8(self, v: i8) -> Result { Ok(self.write.write_i8(v)?) } - fn serialize_i16(self, v: i16) -> Result<()> { + fn serialize_i16(self, v: i16) -> Result { Ok(self.write.write_i16(v)?) } - fn serialize_i32(self, v: i32) -> Result<()> { + fn serialize_i32(self, v: i32) -> Result { Ok(self.write.write_i32(v)?) } - fn serialize_i64(self, v: i64) -> Result<()> { + fn serialize_i64(self, v: i64) -> Result { Ok(self.write.write_i64(v)?) } - fn serialize_u8(self, v: u8) -> Result<()> { + fn serialize_u8(self, v: u8) -> Result { Ok(self.write.write_u8(v)?) } - fn serialize_u16(self, v: u16) -> Result<()> { + fn serialize_u16(self, v: u16) -> Result { Ok(self.write.write_u16(v)?) } - fn serialize_u32(self, v: u32) -> Result<()> { + fn serialize_u32(self, v: u32) -> Result { Ok(self.write.write_u32(v)?) } - fn serialize_u64(self, v: u64) -> Result<()> { + fn serialize_u64(self, v: u64) -> Result { Ok(self.write.write_u64(v)?) } - fn serialize_f32(self, v: f32) -> Result<()> { + fn serialize_f32(self, v: f32) -> Result { Ok(self.write.write_f32(v)?) } - fn serialize_f64(self, v: f64) -> Result<()> { + fn serialize_f64(self, v: f64) -> Result { 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 { + 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 { Ok(self.write.write_string(v)?) } - fn serialize_bytes(self, v: &[u8]) -> Result<()> { + fn serialize_bytes(self, v: &[u8]) -> Result { 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 { + 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(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(self, v: &T) -> Result 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 { + 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 { + 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.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(self, name: &'static str, value: &T) -> - Result<()> where T: Serialize + Result 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 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) -> Result { - 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.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.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.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) -> Result { - 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.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.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(&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(&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 { + 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(&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 { + 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(&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 { + 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(&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 { + 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(&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 { + 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(&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 { + 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(&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 { + Ok(self.ser.write.end_compound(self.c)?) } } -pub fn to_writer(write: &mut W, value: &T) -> Result<()> { +pub fn to_writer(write: &mut W, value: &T) -> Result { let mut ser: Serializer<'_, W> = Serializer::new(write); value.serialize(&mut ser) } diff --git a/implementations/rust/src/value/decoder.rs b/implementations/rust/src/value/decoder.rs index 705135c..6d34b6e 100644 --- a/implementations/rust/src/value/decoder.rs +++ b/implementations/rust/src/value/decoder.rs @@ -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> { diff --git a/implementations/rust/src/value/encoder.rs b/implementations/rust/src/value/encoder.rs index abdf3f3..52d0ab4 100644 --- a/implementations/rust/src/value/encoder.rs +++ b/implementations/rust/src/value/encoder.rs @@ -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> { let mut buf: Vec = 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 { 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 { 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()?) } diff --git a/implementations/rust/src/value/mod.rs b/implementations/rust/src/value/mod.rs index 4bc3a02..a93086f 100644 --- a/implementations/rust/src/value/mod.rs +++ b/implementations/rust/src/value/mod.rs @@ -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; diff --git a/implementations/rust/src/value/constants.rs b/implementations/rust/src/value/packed/constants.rs similarity index 100% rename from implementations/rust/src/value/constants.rs rename to implementations/rust/src/value/packed/constants.rs diff --git a/implementations/rust/src/value/packed/mod.rs b/implementations/rust/src/value/packed/mod.rs new file mode 100644 index 0000000..bc98591 --- /dev/null +++ b/implementations/rust/src/value/packed/mod.rs @@ -0,0 +1,6 @@ +pub mod constants; +pub mod reader; +pub mod writer; + +pub use reader::PackedReader; +pub use writer::PackedWriter; diff --git a/implementations/rust/src/value/packed/reader.rs b/implementations/rust/src/value/packed/reader.rs new file mode 100644 index 0000000..6f43d53 --- /dev/null +++ b/implementations/rust/src/value/packed/reader.rs @@ -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 { + self.source.peek() + } + fn readbytes(&mut self, count: usize) -> IOResult> { + self.source.readbytes(count) + } + fn readbytes_into(&mut self, bs: &mut [u8]) -> IOResult<()> { + self.source.readbytes_into(bs) + } +} + +fn out_of_range>(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 { + 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 { + 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 { + if arg < 15 { + Ok(usize::from(arg)) + } else { + self.varint() + } + } + + fn peekend(&mut self) -> IOResult { + if self.peek()? == 4 { + self.skip()?; + Ok(true) + } else { + Ok(false) + } + } + + fn gather_chunks(&mut self) -> IOResult> { + 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> { + 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> + { + 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 { + 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(&mut self, f: F) -> ReaderResult + where + F: FnOnce(u128) -> Option + { + 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(&mut self, f: F) -> ReaderResult + where + F: FnOnce(i128) -> Option + { + 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> { + 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) -> ReaderResult> { + 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> { + 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> { + self.next_compound(CompoundMinor::Sequence, ExpectedKind::Sequence) + } + + fn open_set(&mut self) -> ReaderResult> { + self.next_compound(CompoundMinor::Set, ExpectedKind::Set) + } + + fn open_dictionary(&mut self) -> ReaderResult> { + 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 { + Ok(self.peekend()?) + } + + fn next_boolean(&mut self) -> ReaderResult { + 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 { self.next_signed(|n| n.to_i8()) } + fn next_i16(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i16()) } + fn next_i32(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i32()) } + fn next_i64(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i64()) } + fn next_i128(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i128()) } + + fn next_u8(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u8()) } + fn next_u16(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u16()) } + fn next_u32(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u32()) } + fn next_u64(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u64()) } + fn next_u128(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u128()) } + + fn next_float(&mut self) -> ReaderResult { + 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 { + 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> { + Ok(decodestr(self.next_atomic(AtomMinor::String, ExpectedKind::Symbol)?)?) + } + + fn next_bytestring(&mut self) -> ReaderResult> { + self.next_atomic(AtomMinor::ByteString, ExpectedKind::Symbol) + } + + fn next_symbol(&mut self) -> ReaderResult> { + 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; + fn next(&mut self) -> Option { + 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; + fn next(&mut self) -> Option { + 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> { + 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 { + 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>>( + minor: CompoundMinor, + mut iter: I +) -> + IOResult +{ + match minor { + CompoundMinor::Record => { + let vs = iter.collect::>>()?; + 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::>>()?; + 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()) + } + } +} diff --git a/implementations/rust/src/value/packed/writer.rs b/implementations/rust/src/value/packed/writer.rs new file mode 100644 index 0000000..4d6797b --- /dev/null +++ b/implementations/rust/src/value/packed/writer.rs @@ -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: &mut PackedWriter, op: Op, arg: u8) -> Result<()> { + w.0.write_all(&[(u8::from(op) << 4) | (arg & 15)]) +} + +pub fn write_header(w: &mut PackedWriter, 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: &mut PackedWriter, 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 { + 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 { + 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> { + write_op(self, Op::Misc(2), Op::Atom(AtomMinor::String).into())?; + Ok(Some(())) + } + + fn stream_bytes(&mut self) -> Result> { + write_op(self, Op::Misc(2), Op::Atom(AtomMinor::ByteString).into())?; + Ok(Some(())) + } + + fn stream_symbol(&mut self) -> Result> { + 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 { + write_header(self, Op::Compound(CompoundMinor::Record), field_count + 1)?; + Ok(false) + } + + fn start_sequence(&mut self, item_count: u64) -> Result { + write_header(self, Op::Compound(CompoundMinor::Sequence), item_count)?; + Ok(false) + } + + fn start_set(&mut self, item_count: u64) -> Result { + write_header(self, Op::Compound(CompoundMinor::Set), item_count)?; + Ok(false) + } + + fn stream_record(&mut self) -> Result> { + write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Record).into())?; + Ok(Some(true)) + } + + fn stream_sequence(&mut self) -> Result> { + write_op(self, Op::Misc(2), Op::Compound(CompoundMinor::Sequence).into())?; + Ok(Some(true)) + } + + fn stream_set(&mut self) -> Result> { + 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 { + write_header(self, Op::Compound(CompoundMinor::Dictionary), entry_count << 1)?; + Ok(false) + } + + fn stream_dictionary(&mut self) -> Result> { + 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 { + 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) + } +} diff --git a/implementations/rust/src/value/reader.rs b/implementations/rust/src/value/reader.rs index b4b4735..460afff 100644 --- a/implementations/rust/src/value/reader.rs +++ b/implementations/rust/src/value/reader.rs @@ -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 = std::result::Result; pub type ReaderResult = std::result::Result; -#[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 { - 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>> { - 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> - { - 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> - { - 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>; - fn open_record(&mut self, arity: Option) -> ReaderResult; - fn open_sequence_or_set(&mut self) -> ReaderResult; - fn open_sequence(&mut self) -> ReaderResult; - fn open_set(&mut self) -> ReaderResult; - fn open_dictionary(&mut self) -> ReaderResult; - fn close_compound_counted(&mut self, minor: CompoundMinor) -> ReaderResult<()>; - fn close_compound_stream(&mut self, minor: CompoundMinor) -> ReaderResult; + fn open_record(&mut self, arity: Option) -> ReaderResult>; + fn open_sequence_or_set(&mut self) -> ReaderResult>; + fn open_sequence(&mut self) -> ReaderResult>; + fn open_set(&mut self) -> ReaderResult>; + fn open_dictionary(&mut self) -> ReaderResult>; + fn close_compound_counted(&mut self, info: Self::CompoundInfo) -> ReaderResult<()>; + fn close_compound_stream(&mut self, info: Self::CompoundInfo) -> ReaderResult; //--------------------------------------------------------------------------- @@ -158,7 +61,7 @@ pub trait Reader<'de> { } fn open_option(&mut self) -> - ReaderResult<(bool, CompoundBody)> + ReaderResult<(bool, CompoundBody)> where Self: Sized { @@ -173,7 +76,7 @@ pub trait Reader<'de> { } fn open_simple_record(&mut self, name: &str, arity: Option) -> - ReaderResult + ReaderResult> 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> { (*self).next(read_annotations) } - fn open_record(&mut self, arity: Option) -> ReaderResult { + fn open_record(&mut self, arity: Option) -> ReaderResult> { (*self).open_record(arity) } - fn open_sequence_or_set(&mut self) -> ReaderResult { + fn open_sequence_or_set(&mut self) -> ReaderResult> { (*self).open_sequence_or_set() } - fn open_sequence(&mut self) -> ReaderResult { + fn open_sequence(&mut self) -> ReaderResult> { (*self).open_sequence() } - fn open_set(&mut self) -> ReaderResult { + fn open_set(&mut self) -> ReaderResult> { (*self).open_set() } - fn open_dictionary(&mut self) -> ReaderResult { + fn open_dictionary(&mut self) -> ReaderResult> { (*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 { - (*self).close_compound_stream(minor) + fn close_compound_stream(&mut self, info: Self::CompoundInfo) -> ReaderResult { + (*self).close_compound_stream(info) + } +} + +#[derive(Debug)] +pub struct CompoundBody { + pub info: I, + pub limit: CompoundLimit, +} + +#[derive(Debug)] +pub enum CompoundLimit { + Counted(usize), + Streaming, + Finished, +} + +impl CompoundBody { + 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 { + 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>> { + 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> + { + 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> + { + 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 { - self.source.peek() - } - fn readbytes(&mut self, count: usize) -> IOResult> { - 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: 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 { - 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 { - 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 { - if arg < 15 { - Ok(usize::from(arg)) - } else { - self.varint() - } - } - - fn peekend(&mut self) -> IOResult { - if self.peek()? == 4 { - self.skip()?; - Ok(true) - } else { - Ok(false) - } - } - - fn gather_chunks(&mut self) -> IOResult> { - 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> { - 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 - { - 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 { - 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(&mut self, f: F) -> ReaderResult - where - F: FnOnce(u128) -> Option - { - 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(&mut self, f: F) -> ReaderResult - where - F: FnOnce(i128) -> Option - { - 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> { - 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) -> ReaderResult { - 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 { - 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 { - self.next_compound(CompoundMinor::Sequence, ExpectedKind::Sequence) - } - - fn open_set(&mut self) -> ReaderResult { - self.next_compound(CompoundMinor::Set, ExpectedKind::Set) - } - - fn open_dictionary(&mut self) -> ReaderResult { - 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 { - Ok(self.peekend()?) - } - - fn next_boolean(&mut self) -> ReaderResult { - 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 { self.next_signed(|n| n.to_i8()) } - fn next_i16(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i16()) } - fn next_i32(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i32()) } - fn next_i64(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i64()) } - fn next_i128(&mut self) -> ReaderResult { self.next_signed(|n| n.to_i128()) } - - fn next_u8(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u8()) } - fn next_u16(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u16()) } - fn next_u32(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u32()) } - fn next_u64(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u64()) } - fn next_u128(&mut self) -> ReaderResult { self.next_unsigned(|n| n.to_u128()) } - - fn next_float(&mut self) -> ReaderResult { - 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 { - 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> { - Ok(decodestr(self.next_atomic(AtomMinor::String, ExpectedKind::Symbol)?)?) - } - - fn next_bytestring(&mut self) -> ReaderResult> { - self.next_atomic(AtomMinor::ByteString, ExpectedKind::Symbol) - } - - fn next_symbol(&mut self) -> ReaderResult> { - 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; - fn next(&mut self) -> Option { - 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; - fn next(&mut self) -> Option { - 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> { - 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 { - 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>>( - minor: CompoundMinor, - mut iter: I -) -> - IOResult -{ - match minor { - CompoundMinor::Record => { - let vs = iter.collect::>>()?; - 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::>>()?; - 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()) - } - } -} diff --git a/implementations/rust/src/value/writer.rs b/implementations/rust/src/value/writer.rs index 22b685b..6ce7bd6 100644 --- a/implementations/rust/src/value/writer.rs +++ b/implementations/rust/src/value/writer.rs @@ -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 = std::result::Result; 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; + 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; - 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; - 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; + fn write_f64(&mut self, v: f64) -> Result; - 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; + 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 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; + fn write_bytes(&mut self, v: &[u8]) -> Result; + fn write_symbol(&mut self, v: &str) -> Result; - 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>; + fn stream_bytes(&mut self) -> Result>; + fn stream_symbol(&mut self) -> Result>; + fn extend_atom(&mut self, s: &mut Self::StreamedAtom, bs: &[u8]) -> Result<()>; + fn end_atom(&mut self, s: Self::StreamedAtom) -> Result; - fn close_stream(&mut self) -> Result; + fn start_record(&mut self, field_count: u64) -> Result; + fn start_sequence(&mut self, item_count: u64) -> Result; + fn start_set(&mut self, item_count: u64) -> Result; + fn stream_record(&mut self) -> Result>; + fn stream_sequence(&mut self) -> Result>; + fn stream_set(&mut self) -> Result>; + fn extend_compound(&mut self, s: &mut Self::Compound, value_p: Self::Pointer) -> Result<()>; + fn end_compound(&mut self, s: Self::Compound) -> Result; + + fn start_dictionary(&mut self, entry_count: u64) -> Result; + fn stream_dictionary(&mut self) -> Result>; + fn extend_dictionary_key(&mut self, s: &mut Self::Dictionary, key_p: Self::Pointer) -> Result; + 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; } -pub fn varint(w: &mut W, mut v: usize) -> Result { +pub fn bigvarint(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: &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: &mut W, mut v: usize) -> Result { } } } - -pub fn write_op(w: &mut W, op: Op, arg: u8) -> Result { - w.write_all(&[(u8::from(op) << 4) | (arg & 15)]) -} - -pub fn write_header(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: &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 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) - } -}