Remove decoder/encoder; undoes performance regression

This commit is contained in:
Tony Garnock-Jones 2020-07-08 15:42:58 +02:00
parent 28101cc7d1
commit 9f83756931
12 changed files with 176 additions and 213 deletions

View File

@ -1,5 +1,5 @@
use criterion::{criterion_group, criterion_main, Criterion};
use preserves::value::{self, decoder, encoder, PackedReader, PackedWriter, reader::Reader};
use preserves::value::{self, Reader, Writer, PackedReader, PackedWriter};
use preserves::{de, ser};
use std::io::Read;
use std::io::BufReader;
@ -14,14 +14,14 @@ pub fn bench_decoder_bytes(c: &mut Criterion) {
let mut bs = vec![];
fh.read_to_end(&mut bs).ok();
c.bench_function("decode samples.bin via bytes", |b| b.iter_with_large_drop(
|| decoder::from_bytes(&bs[..]).demand_next().unwrap()));
|| PackedReader::decode_bytes(&bs[..]).demand_next(true).unwrap()));
}
pub fn bench_decoder_file(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
c.bench_function("decode samples.bin via file", |b| b.iter_with_large_drop(|| {
fh.seek(SeekFrom::Start(0)).ok();
decoder::from_read(&mut fh).demand_next().unwrap()
PackedReader::decode_read(&mut fh).demand_next(true).unwrap()
}));
}
@ -29,16 +29,16 @@ pub fn bench_decoder_buffered_file(c: &mut Criterion) {
let mut fh = BufReader::new(std::fs::File::open("../../tests/samples.bin").unwrap());
c.bench_function("decode samples.bin via buffered file", |b| b.iter_with_large_drop(|| {
fh.seek(SeekFrom::Start(0)).ok();
decoder::from_read(&mut fh).demand_next().unwrap()
PackedReader::decode_read(&mut fh).demand_next(true).unwrap()
}));
}
pub fn bench_encoder(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
let v = decoder::from_read(&mut fh).demand_next().unwrap();
let v = PackedReader::decode_read(&mut fh).demand_next(true).unwrap();
c.bench_function("encode samples.bin", |b| b.iter_with_large_drop(|| {
let mut bs = vec![];
encoder::Encoder::new(&mut PackedWriter(&mut bs)).write(&v).unwrap();
PackedWriter(&mut bs).write(&v).unwrap();
bs
}));
}
@ -66,7 +66,7 @@ pub fn bench_decoder_de(c: &mut Criterion) {
let mut bs = vec![];
fh.read_to_end(&mut bs).ok();
c.bench_function("decode-then-deserialize samples.bin", |b| b.iter_with_large_drop(
|| value::de::from_value::<TestCases>(&decoder::from_bytes(&bs[..]).demand_next().unwrap()).unwrap()));
|| value::de::from_value::<TestCases>(&PackedReader::decode_bytes(&bs[..]).demand_next(true).unwrap()).unwrap()));
}
pub fn bench_ser_encoder(c: &mut Criterion) {
@ -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 PackedWriter(&mut bs)).write(&value::ser::to_value(&v)).unwrap();
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 = PackedReader::from_bytes(&bs[..]);
let mut r = PackedReader::decode_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 = PackedReader::from_bytes(&bs[..]);
let mut r = PackedReader::decode_bytes(&bs[..]);
while let Some(_) = r.next(false).unwrap() {}
})
});
@ -107,16 +107,15 @@ 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 = PackedReader::from_read(&mut fh);
let mut r = PackedReader::decode_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 w = PackedWriter(&mut bs);
let mut e = encoder::Encoder::new(&mut w);
for v in &vs {
e.write(&v).unwrap();
w.write(&v).unwrap();
}
bs
})

View File

@ -1,4 +1,4 @@
use preserves::{de, value, value::decoder};
use preserves::{de, value::{self, Reader, PackedReader}};
use serde::{Serialize, Deserialize};
use std::fs::File;
use std::io::Error;
@ -33,7 +33,7 @@ enum Variety {
}
fn try_file(kind: &str, path: &str) -> Result<(), Error> {
let fruits_value = decoder::from_read(&mut File::open(path)?).demand_next()?;
let fruits_value = PackedReader::decode_read(&mut File::open(path)?).demand_next(true)?;
println!("{:?}", fruits_value);
let fruits1: Vec<Fruit> = value::de::from_value(&fruits_value)?;

View File

@ -12,7 +12,7 @@ pub mod value;
mod dom {
use super::value::{
Value, IOValue, NestedValue, PlainValue, Domain,
encoder::encode_bytes,
PackedWriter,
};
#[derive(Debug, Hash, Clone, Ord, PartialEq, Eq, PartialOrd)]
@ -36,7 +36,7 @@ mod dom {
Value::Domain(Dom::One).wrap(),
Value::from(2).wrap()])
.wrap();
assert_eq!(encode_bytes(&v.to_io_value()).unwrap(),
assert_eq!(PackedWriter::encode(&v.to_io_value()).unwrap(),
[147, 49, 100, 255, 255, 255, 255, 50]);
}
@ -45,7 +45,7 @@ mod dom {
Value::Domain(Dom::Two).wrap(),
Value::from(2).wrap()])
.wrap();
assert_eq!(encode_bytes(&v.to_io_value()).unwrap(),
assert_eq!(PackedWriter::encode(&v.to_io_value()).unwrap(),
[147, 49, 120, 68, 111, 109, 58, 58, 84, 119, 111, 50]);
}
}
@ -229,7 +229,7 @@ mod value_tests {
#[cfg(test)]
mod decoder_tests {
use crate::value::{Value, NestedValue, decoder};
use crate::value::{Value, NestedValue, PackedReader, ConfiguredReader};
use crate::de::from_bytes;
use crate::error::{Error, ExpectedKind, is_eof_io_error};
@ -251,7 +251,7 @@ mod decoder_tests {
#[test] fn skip_annotations_noskip() {
let mut buf = &b"\x0521"[..];
let mut d = decoder::from_bytes(&mut buf);
let mut d = ConfiguredReader::new(PackedReader::decode_bytes(&mut buf));
let v = d.demand_next().unwrap();
assert_eq!(v.annotations().slice().len(), 1);
assert_eq!(v.annotations().slice()[0], Value::from(2).wrap());
@ -260,7 +260,7 @@ mod decoder_tests {
#[test] fn skip_annotations_skip() {
let mut buf = &b"\x0521"[..];
let mut d = decoder::from_bytes(&mut buf);
let mut d = ConfiguredReader::new(PackedReader::decode_bytes(&mut buf));
d.set_read_annotations(false);
let v = d.demand_next().unwrap();
assert_eq!(v.annotations().slice().len(), 0);
@ -270,12 +270,12 @@ mod decoder_tests {
#[test] fn multiple_values_buf_advanced() {
let mut buf = &b"\x81tPing\x81tPong"[..];
assert_eq!(buf.len(), 12);
let mut d = decoder::from_bytes(&mut buf);
assert_eq!(d.read.source.index, 0);
let mut d = ConfiguredReader::new(PackedReader::decode_bytes(&mut buf));
assert_eq!(d.reader.source.index, 0);
assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record0("Ping"));
assert_eq!(d.read.source.index, 6);
assert_eq!(d.reader.source.index, 6);
assert_eq!(d.demand_next().unwrap().value(), &Value::simple_record0("Pong"));
assert_eq!(d.read.source.index, 12);
assert_eq!(d.reader.source.index, 12);
assert!(d.next().is_none());
assert!(if let Err(e) = d.demand_next() { is_eof_io_error(&e) } else { false });
}
@ -387,7 +387,6 @@ mod serde_tests {
use crate::symbol::Symbol;
use crate::de::from_bytes as deserialize_from_bytes;
use crate::value::de::from_value as deserialize_from_value;
use crate::value::encoder::encode_bytes;
use crate::value::to_value;
use crate::value::{Value, IOValue, Map, Set};
use crate::value::packed::PackedWriter;
@ -476,7 +475,7 @@ mod serde_tests {
0x3, 0x40, 0x28, 0xb0, 0xfc, 0xd3, 0x24, 0xd5, 0xa2, // 12.3456789
];
let v_bytes_1 = encode_bytes(&w).unwrap();
let v_bytes_1 = PackedWriter::encode(&w).unwrap();
println!("== w bytes = {:?}", v_bytes_1);
assert_eq!(expected_bytes, v_bytes_1);

View File

@ -1,6 +1,5 @@
use serde::Serialize;
use super::value::writer::Writer;
use super::value::Encoder;
pub use super::error::Error;
type Result<T> = std::result::Result<T, Error>;
@ -148,7 +147,7 @@ impl<'a, 'b, W: Writer> serde::Serializer for &'a mut Serializer<'b, W> {
{
match super::value::magic::receive_output_value(name, value) {
Some(v) => {
Ok(Encoder::new(self.write).write(&v)?)
Ok(self.write.write(&v)?)
}
None => {
// TODO: This is apparently discouraged, and we should apparently just serialize `value`?

View File

@ -1,49 +0,0 @@
use std::marker::PhantomData;
use super::packed::PackedReader;
use super::reader::{self, Reader};
use super::value::IOValue;
pub use super::reader::IOResult as Result;
pub struct Decoder<'de, R: Reader<'de>> {
pub read: R,
read_annotations: bool,
phantom: PhantomData<&'de ()>,
}
pub fn from_bytes<'de>(bytes: &'de [u8]) ->
Decoder<'de, PackedReader<'de, reader::BytesBinarySource<'de>>>
{
Decoder::new(PackedReader::from_bytes(bytes))
}
pub fn from_read<'de, 'a, IOR: std::io::Read>(read: &'a mut IOR) ->
Decoder<'de, PackedReader<'de, reader::IOBinarySource<'a, IOR>>>
{
Decoder::new(PackedReader::from_read(read))
}
impl<'de, R: Reader<'de>> Decoder<'de, R> {
pub fn new(read: R) -> Self {
Decoder { read, read_annotations: true, phantom: PhantomData }
}
pub fn set_read_annotations(&mut self, read_annotations: bool) {
self.read_annotations = read_annotations
}
pub fn demand_next(&mut self) -> Result<IOValue> {
self.read.demand_next(self.read_annotations)
}
}
impl<'de, R: Reader<'de>> std::iter::Iterator for Decoder<'de, R> {
type Item = Result<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
match self.read.next(self.read_annotations) {
Err(e) => Some(Err(e)),
Ok(None) => None,
Ok(Some(v)) => Some(Ok(v)),
}
}
}

View File

@ -1,89 +0,0 @@
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;
pub struct Encoder<'a, W: Writer> {
pub write: &'a mut W,
}
pub fn encode_bytes(v: &IOValue) -> std::io::Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
Encoder::new(&mut PackedWriter(&mut buf)).write(v)?;
Ok(buf)
}
impl<'a, W: Writer> Encoder<'a, W> {
pub fn new(write: &'a mut W) -> Self {
Encoder { write }
}
pub fn write(&mut self, v: &IOValue) -> Result<W::Pointer> {
match v.annotations().maybe_slice() {
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)
}
}
}
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),
Value::Double(Double(d)) => self.write.write_f64(*d),
Value::SignedInteger(n) => match n.repr() {
SignedIntegerRepr::I128(i) => self.write.write_i128(*i),
SignedIntegerRepr::U128(u) => self.write.write_u128(*u),
SignedIntegerRepr::Big(ref n) => self.write.write_int(n),
}
Value::String(ref s) => self.write.write_string(s),
Value::ByteString(ref bs) => self.write.write_bytes(bs),
Value::Symbol(ref s) => self.write.write_symbol(s),
Value::Record(r) => {
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) => {
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) => {
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) => {
let mut d = self.write.start_dictionary(vs.len() as u64)?;
for (k, v) in vs {
let p = self.write(k)?;
let kp = self.write.extend_dictionary_key(&mut d, p)?;
let p = self.write(v)?;
self.write.extend_dictionary_value(&mut d, kp, p)?;
}
self.write.end_dictionary(d)
}
Value::Domain(ref d) => self.write(&d.as_preserves()?)
}
}
}

View File

@ -1,6 +1,4 @@
pub mod de;
pub mod decoder;
pub mod encoder;
pub mod magic;
pub mod packed;
pub mod reader;
@ -11,10 +9,9 @@ pub mod writer;
pub use de::Deserializer;
pub use de::from_value;
pub use decoder::Decoder;
pub use encoder::Encoder;
pub use packed::PackedReader;
pub use packed::PackedWriter;
pub use reader::ConfiguredReader;
pub use reader::Reader;
pub use ser::Serializer;
pub use ser::to_value;

View File

@ -3,7 +3,6 @@ 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};
@ -14,6 +13,7 @@ use super::super::reader::{
BytesBinarySource,
CompoundBody,
CompoundLimit,
ConfiguredReader,
IOBinarySource,
IOResult,
Reader,
@ -47,13 +47,13 @@ fn out_of_range<I: Into<BigInt>>(i: I) -> error::Error {
}
impl<'de> PackedReader<'de, BytesBinarySource<'de>> {
pub fn from_bytes(bytes: &'de [u8]) -> Self {
pub fn decode_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 {
pub fn decode_read(read: &'a mut IOR) -> Self {
PackedReader::new(IOBinarySource::new(read))
}
}
@ -308,11 +308,7 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
Op::Atom(minor) =>
decodebinary(minor, Cow::Owned(self.gather_chunks()?))?,
Op::Compound(minor) => decodecompound(minor, DelimitedStream {
reader: ConfiguredPackedReader {
reader: self,
read_annotations,
phantom: PhantomData,
},
reader: self.configured(read_annotations),
})?,
_ => Err(io_syntax_error("Invalid format C start byte"))?,
}
@ -334,11 +330,7 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
(Op::Compound(minor), arg) => {
let count = self.wirelength(arg)?;
decodecompound(minor, CountedStream {
reader: ConfiguredPackedReader {
reader: self,
read_annotations,
phantom: PhantomData,
},
reader: self.configured(read_annotations),
count,
})?
}
@ -473,18 +465,12 @@ impl<'de, S: BinarySource<'de>> Reader<'de> for PackedReader<'de, S> {
}
}
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>,
struct CountedStream<'de, R: Reader<'de>> {
reader: ConfiguredReader<'de, R>,
count: usize,
}
impl<'de, 'a, S: BinarySource<'de>> Iterator for CountedStream<'de, 'a, S>
impl<'de, R: Reader<'de>> Iterator for CountedStream<'de, R>
{
type Item = IOResult<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
@ -494,11 +480,11 @@ impl<'de, 'a, S: BinarySource<'de>> Iterator for CountedStream<'de, 'a, S>
}
}
struct DelimitedStream<'de, 'a, S: BinarySource<'de>> {
reader: ConfiguredPackedReader<'de, 'a, S>,
struct DelimitedStream<'a, 'de, S: BinarySource<'de>> {
reader: ConfiguredReader<'de, &'a mut PackedReader<'de, S>>,
}
impl<'de, 'a, S: BinarySource<'de>> Iterator for DelimitedStream<'de, 'a, S>
impl<'a, 'de, S: BinarySource<'de>> Iterator for DelimitedStream<'a, 'de, S>
{
type Item = IOResult<IOValue>;
fn next(&mut self) -> Option<Self::Item> {

View File

@ -3,7 +3,7 @@ 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::IOValue;
use super::super::writer::{Writer, Result, varint};
@ -40,6 +40,14 @@ impl<'w, W: std::io::Write> PackedWriter<'w, W> {
}
}
impl<'w> PackedWriter<'w, &'w mut Vec<u8>> {
pub fn encode(v: &IOValue) -> std::io::Result<Vec<u8>> {
let mut buf: Vec<u8> = Vec::new();
PackedWriter(&mut buf).write(v)?;
Ok(buf)
}
}
impl<'w, W: std::io::Write> Writer for PackedWriter<'w, W> {
type Pointer = ();
type Annotation = ();
@ -58,7 +66,7 @@ impl<'w, W: std::io::Write> Writer for PackedWriter<'w, W> {
fn extend_annotation(&mut self, _a: &mut Self::Annotation, annotation: &IOValue) -> Result<()> {
write_header(self, Op::Misc(0), 5)?;
Encoder::new(self).write(annotation)
self.write(annotation)
}
fn end_annotation(&mut self, _a: Self::Annotation, _value_p: Self::Pointer) -> Result<Self::Pointer> {

View File

@ -1,5 +1,6 @@
use std::borrow::Cow;
use std::io::{Read, Error};
use std::marker::PhantomData;
use super::value::{NestedValue, IOValue};
use crate::error::{self, ExpectedKind, Received, io_eof};
@ -89,6 +90,17 @@ pub trait Reader<'de> {
Received::ReceivedRecordWithLabel(label.to_owned())))
}
}
fn configured(self, read_annotations: bool) -> ConfiguredReader<'de, Self>
where
Self: std::marker::Sized
{
ConfiguredReader {
reader: self,
read_annotations,
phantom: PhantomData,
}
}
}
impl<'r, 'de, R: Reader<'de>> Reader<'de> for &'r mut R {
@ -321,3 +333,34 @@ impl<'de> BinarySource<'de> for BytesBinarySource<'de> {
}
}
}
pub struct ConfiguredReader<'de, R: Reader<'de>> {
pub reader: R,
pub read_annotations: bool,
phantom: PhantomData<&'de ()>,
}
impl<'de, R: Reader<'de>> ConfiguredReader<'de, R> {
pub fn new(reader: R) -> Self {
reader.configured(true)
}
pub fn set_read_annotations(&mut self, read_annotations: bool) {
self.read_annotations = read_annotations
}
pub fn demand_next(&mut self) -> IOResult<IOValue> {
self.reader.demand_next(self.read_annotations)
}
}
impl<'de, R: Reader<'de>> std::iter::Iterator for ConfiguredReader<'de, R> {
type Item = IOResult<IOValue>;
fn next(&mut self) -> Option<Self::Item> {
match self.reader.next(self.read_annotations) {
Err(e) => Some(Err(e)),
Ok(None) => None,
Ok(Some(v)) => Some(Ok(v)),
}
}
}

View File

@ -1,7 +1,8 @@
use num;
use num::bigint::BigInt;
use std::io::Error;
use super::value::IOValue;
use super::signed_integer::SignedIntegerRepr;
use super::value::{Domain, Value, NestedValue, IOValue, UnwrappedIOValue, Float, Double};
pub type Result<T> = std::result::Result<T, Error>;
@ -62,6 +63,75 @@ pub trait Writer {
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>;
//---------------------------------------------------------------------------
fn write(&mut self, v: &IOValue) -> Result<Self::Pointer> {
match v.annotations().maybe_slice() {
None => self.write_value(v.value()),
Some(anns) => {
let mut a = self.start_annotation()?;
for ann in anns {
self.extend_annotation(&mut a, ann)?;
}
let p = self.write_value(v.value())?;
self.end_annotation(a, p)
}
}
}
fn write_value(&mut self, v: &UnwrappedIOValue) -> Result<Self::Pointer> {
match v {
Value::Boolean(b) => self.write_bool(*b),
Value::Float(Float(f)) => self.write_f32(*f),
Value::Double(Double(d)) => self.write_f64(*d),
Value::SignedInteger(n) => match n.repr() {
SignedIntegerRepr::I128(i) => self.write_i128(*i),
SignedIntegerRepr::U128(u) => self.write_u128(*u),
SignedIntegerRepr::Big(ref n) => self.write_int(n),
}
Value::String(ref s) => self.write_string(s),
Value::ByteString(ref bs) => self.write_bytes(bs),
Value::Symbol(ref s) => self.write_symbol(s),
Value::Record(r) => {
let mut c = self.start_record(r.arity() as u64)?;
let p = self.write(r.label())?;
self.extend_compound(&mut c, p)?;
for f in r.fields() {
let p = self.write(f)?;
self.extend_compound(&mut c, p)?;
}
self.end_compound(c)
}
Value::Sequence(ref vs) => {
let mut c = self.start_sequence(vs.len() as u64)?;
for v in vs {
let p = self.write(v)?;
self.extend_compound(&mut c, p)?;
}
self.end_compound(c)
}
Value::Set(ref vs) => {
let mut c = self.start_set(vs.len() as u64)?;
for v in vs {
let p = self.write(v)?;
self.extend_compound(&mut c, p)?;
}
self.end_compound(c)
}
Value::Dictionary(ref vs) => {
let mut d = self.start_dictionary(vs.len() as u64)?;
for (k, v) in vs {
let p = self.write(k)?;
let kp = self.extend_dictionary_key(&mut d, p)?;
let p = self.write(v)?;
self.extend_dictionary_value(&mut d, kp, p)?;
}
self.end_dictionary(d)
}
Value::Domain(ref d) => self.write(&d.as_preserves()?)
}
}
}
pub fn bigvarint<W: std::io::Write>(w: &mut W, mut v: u64) -> Result<()> {

View File

@ -1,22 +1,22 @@
use preserves::error::{is_eof_io_error, is_syntax_io_error};
use preserves::symbol::Symbol;
use preserves::value::de::from_value as deserialize_from_value;
use preserves::value::decoder;
use preserves::value::encoder::encode_bytes;
use preserves::value::IOValue;
use preserves::value::PackedReader;
use preserves::value::PackedWriter;
use preserves::value::Reader;
use preserves::value::de::from_value as deserialize_from_value;
use std::iter::Iterator;
mod samples;
use samples::*;
fn decode_all<'de>(bytes: &'de [u8]) -> Result<Vec<IOValue>, std::io::Error> {
let d = decoder::from_bytes(bytes);
d.collect()
PackedReader::decode_bytes(bytes).configured(true).collect()
}
#[test] fn run() -> std::io::Result<()> {
let mut fh = std::fs::File::open("../../tests/samples.bin").unwrap();
let mut d = decoder::from_read(&mut fh);
let mut d = PackedReader::decode_read(&mut fh).configured(true);
let tests: TestCases = deserialize_from_value(&d.next().unwrap().unwrap()).unwrap();
// println!("{:#?}", tests);
@ -24,25 +24,25 @@ fn decode_all<'de>(bytes: &'de [u8]) -> Result<Vec<IOValue>, std::io::Error> {
println!("{:?} ==> {:?}", name, case);
match case {
TestCase::Test(ref bin, ref val) => {
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&PackedWriter::encode(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
assert_eq!(&encode_bytes(val)?, bin);
assert_eq!(&PackedWriter::encode(val)?, bin);
}
TestCase::NondeterministicTest(ref bin, ref val) => {
// The test cases in samples.txt are carefully
// written so that while strictly
// "nondeterministic", the order of keys in
// dictionaries follows Preserves order.
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&PackedWriter::encode(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
assert_eq!(&encode_bytes(val)?, bin);
assert_eq!(&PackedWriter::encode(val)?, bin);
}
TestCase::StreamingTest(ref bin, ref val) => {
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&PackedWriter::encode(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
}
TestCase::DecodeTest(ref bin, ref val) => {
assert_eq!(&decode_all(&encode_bytes(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&PackedWriter::encode(val)?[..])?, &[val.clone()]);
assert_eq!(&decode_all(&bin[..])?, &[val.clone()]);
}
TestCase::ParseError(_) => (),
@ -59,14 +59,14 @@ fn decode_all<'de>(bytes: &'de [u8]) -> Result<Vec<IOValue>, std::io::Error> {
}
}
TestCase::DecodeShort(ref bin) => {
assert!(if let Err(e) = decoder::from_bytes(bin).next().unwrap() {
assert!(if let Err(e) = PackedReader::decode_bytes(bin).configured(true).next().unwrap() {
is_eof_io_error(&e)
} else {
false
})
}
TestCase::DecodeEOF(ref bin) => {
assert!(decoder::from_bytes(bin).next().is_none());
assert!(PackedReader::decode_bytes(bin).configured(true).next().is_none());
}
}
}