Take more advantage of use std::io; and fix benches

This commit is contained in:
Tony Garnock-Jones 2021-07-05 13:00:30 +02:00
parent 7e76503779
commit e30ade6ed3
10 changed files with 86 additions and 77 deletions

View File

@ -39,7 +39,7 @@ where
#[derive(Debug)] #[derive(Debug)]
pub enum ParseError { pub enum ParseError {
ConformanceError, ConformanceError,
IO(std::io::Error), IO(io::Error),
Preserves(preserves::error::Error), Preserves(preserves::error::Error),
} }
@ -57,8 +57,8 @@ impl std::fmt::Display for ParseError {
impl std::error::Error for ParseError {} impl std::error::Error for ParseError {}
impl From<std::io::Error> for ParseError { impl From<io::Error> for ParseError {
fn from(v: std::io::Error) -> Self { fn from(v: io::Error) -> Self {
ParseError::IO(v) ParseError::IO(v)
} }
} }
@ -69,11 +69,11 @@ impl From<preserves::error::Error> for ParseError {
} }
} }
impl From<ParseError> for std::io::Error { impl From<ParseError> for io::Error {
fn from(v: ParseError) -> Self { fn from(v: ParseError) -> Self {
match v { match v {
ParseError::ConformanceError => ParseError::ConformanceError =>
std::io::Error::new(std::io::ErrorKind::InvalidData, INPUT_NOT_CONFORMANT), io::Error::new(io::ErrorKind::InvalidData, INPUT_NOT_CONFORMANT),
ParseError::IO(e) => e, ParseError::IO(e) => e,
ParseError::Preserves(e) => e.into(), ParseError::Preserves(e) => e.into(),
} }

View File

@ -1,50 +1,57 @@
use criterion::{criterion_group, criterion_main, Criterion}; use criterion::{criterion_group, criterion_main, Criterion};
use preserves::value::{self, Reader, Writer, PackedReader, PackedWriter}; use preserves::de;
use preserves::{de, ser}; use preserves::ser;
use preserves::value::BinarySource;
use preserves::value::BytesBinarySource;
use preserves::value::IOBinarySource;
use preserves::value::IOValueDomainCodec;
use preserves::value::PackedWriter;
use preserves::value::Reader;
use preserves::value::Writer;
use preserves::value::packed::annotated_iovalue_from_bytes;
use preserves::value;
use std::fs::File;
use std::io::Read; use std::io::Read;
use std::io::BufReader; use std::io::Seek;
use std::io::{Seek, SeekFrom}; use std::io;
#[path = "../tests/samples/mod.rs"] #[path = "../tests/samples/mod.rs"]
mod samples; mod samples;
use samples::TestCases; use samples::TestCases;
pub fn bench_decoder_bytes(c: &mut Criterion) { pub fn bench_decoder_bytes(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
let mut bs = vec![]; let mut bs = vec![];
fh.read_to_end(&mut bs).ok(); fh.read_to_end(&mut bs).ok();
c.bench_function("decode samples.bin via bytes", |b| b.iter_with_large_drop( c.bench_function("decode samples.bin via bytes", |b| b.iter_with_large_drop(
|| PackedReader::decode_bytes(&bs[..]).demand_next(true).unwrap())); || annotated_iovalue_from_bytes(&bs[..]).unwrap()));
} }
pub fn bench_decoder_file(c: &mut Criterion) { pub fn bench_decoder_file(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
c.bench_function("decode samples.bin via file", |b| b.iter_with_large_drop(|| { c.bench_function("decode samples.bin via file", |b| b.iter_with_large_drop(|| {
fh.seek(SeekFrom::Start(0)).ok(); fh.seek(io::SeekFrom::Start(0)).ok();
PackedReader::decode_read(&mut fh).demand_next(true).unwrap() IOBinarySource::new(&mut fh).packed_iovalues().demand_next(true).unwrap()
})); }));
} }
pub fn bench_decoder_buffered_file(c: &mut Criterion) { pub fn bench_decoder_buffered_file(c: &mut Criterion) {
let mut fh = BufReader::new(std::fs::File::open("../../../tests/samples.bin").unwrap()); let mut fh = io::BufReader::new(File::open("../../../tests/samples.bin").unwrap());
c.bench_function("decode samples.bin via buffered file", |b| b.iter_with_large_drop(|| { c.bench_function("decode samples.bin via buffered file", |b| b.iter_with_large_drop(|| {
fh.seek(SeekFrom::Start(0)).ok(); fh.seek(io::SeekFrom::Start(0)).ok();
PackedReader::decode_read(&mut fh).demand_next(true).unwrap() IOBinarySource::new(&mut fh).packed_iovalues().demand_next(true).unwrap()
})); }));
} }
pub fn bench_encoder(c: &mut Criterion) { pub fn bench_encoder(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
let v = PackedReader::decode_read(&mut fh).demand_next(true).unwrap(); let v = IOBinarySource::new(&mut fh).packed_iovalues().demand_next(true).unwrap();
c.bench_function("encode samples.bin", |b| b.iter_with_large_drop(|| { c.bench_function("encode samples.bin", |b| b.iter_with_large_drop(
let mut bs = vec![]; || PackedWriter::encode_iovalue(&v).unwrap()));
PackedWriter::new(&mut bs).write(&v).unwrap();
bs
}));
} }
pub fn bench_de(c: &mut Criterion) { pub fn bench_de(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
let mut bs = vec![]; let mut bs = vec![];
fh.read_to_end(&mut bs).ok(); fh.read_to_end(&mut bs).ok();
c.bench_function("deserialize samples.bin", |b| b.iter_with_large_drop( c.bench_function("deserialize samples.bin", |b| b.iter_with_large_drop(
@ -52,7 +59,7 @@ pub fn bench_de(c: &mut Criterion) {
} }
pub fn bench_ser(c: &mut Criterion) { pub fn bench_ser(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
let v: TestCases = de::from_read(&mut fh).unwrap(); let v: TestCases = de::from_read(&mut fh).unwrap();
c.bench_function("serialize samples.bin", |b| b.iter_with_large_drop(|| { c.bench_function("serialize samples.bin", |b| b.iter_with_large_drop(|| {
let mut bs = vec![]; let mut bs = vec![];
@ -62,30 +69,28 @@ pub fn bench_ser(c: &mut Criterion) {
} }
pub fn bench_decoder_de(c: &mut Criterion) { pub fn bench_decoder_de(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
let mut bs = vec![]; let mut bs = vec![];
fh.read_to_end(&mut bs).ok(); fh.read_to_end(&mut bs).ok();
c.bench_function("decode-then-deserialize samples.bin", |b| b.iter_with_large_drop( c.bench_function("decode-then-deserialize samples.bin", |b| b.iter_with_large_drop(
|| value::de::from_value::<TestCases>(&PackedReader::decode_bytes(&bs[..]).demand_next(true).unwrap()).unwrap())); || value::de::from_value::<TestCases>(&annotated_iovalue_from_bytes(&bs[..]).unwrap()).unwrap()));
} }
pub fn bench_ser_encoder(c: &mut Criterion) { pub fn bench_ser_encoder(c: &mut Criterion) {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = File::open("../../../tests/samples.bin").unwrap();
let v: TestCases = de::from_read(&mut fh).unwrap(); let v: TestCases = de::from_read(&mut fh).unwrap();
c.bench_function("serialize-then-encode samples.bin", |b| b.iter_with_large_drop(|| { c.bench_function("serialize-then-encode samples.bin", |b| b.iter_with_large_drop(
let mut bs = vec![]; || PackedWriter::encode_iovalue(&value::ser::to_value(&v)).unwrap()));
PackedWriter::new(&mut bs).write(&value::ser::to_value(&v)).unwrap();
bs
}));
} }
pub fn large_testdata_decoder_with_ann(c: &mut Criterion) { pub fn large_testdata_decoder_with_ann(c: &mut Criterion) {
c.bench_function("decode testdata.bin with annotations", |b| { c.bench_function("decode testdata.bin with annotations", |b| {
let mut fh = std::fs::File::open("benches/testdata.bin").unwrap(); let mut fh = File::open("benches/testdata.bin").unwrap();
let mut bs = vec![]; let mut bs = vec![];
fh.read_to_end(&mut bs).ok(); fh.read_to_end(&mut bs).ok();
b.iter(|| { b.iter(|| {
let mut r = PackedReader::decode_bytes(&bs[..]); let mut src = BytesBinarySource::new(&bs[..]);
let mut r = src.packed_iovalues();
while let Some(_) = r.next(true).unwrap() {} while let Some(_) = r.next(true).unwrap() {}
}) })
}); });
@ -93,11 +98,12 @@ pub fn large_testdata_decoder_with_ann(c: &mut Criterion) {
pub fn large_testdata_decoder_without_ann(c: &mut Criterion) { pub fn large_testdata_decoder_without_ann(c: &mut Criterion) {
c.bench_function("decode testdata.bin without annotations", |b| { c.bench_function("decode testdata.bin without annotations", |b| {
let mut fh = std::fs::File::open("benches/testdata.bin").unwrap(); let mut fh = File::open("benches/testdata.bin").unwrap();
let mut bs = vec![]; let mut bs = vec![];
fh.read_to_end(&mut bs).ok(); fh.read_to_end(&mut bs).ok();
b.iter(|| { b.iter(|| {
let mut r = PackedReader::decode_bytes(&bs[..]); let mut src = BytesBinarySource::new(&bs[..]);
let mut r = src.packed_iovalues();
while let Some(_) = r.next(false).unwrap() {} while let Some(_) = r.next(false).unwrap() {}
}) })
}); });
@ -105,17 +111,19 @@ pub fn large_testdata_decoder_without_ann(c: &mut Criterion) {
pub fn large_testdata_encoder(c: &mut Criterion) { pub fn large_testdata_encoder(c: &mut Criterion) {
c.bench_function("encode testdata.bin", |b| { c.bench_function("encode testdata.bin", |b| {
let mut fh = BufReader::new(std::fs::File::open("benches/testdata.bin").unwrap()); let mut fh = io::BufReader::new(File::open("benches/testdata.bin").unwrap());
let mut vs = vec![]; let mut vs = vec![];
let mut r = PackedReader::decode_read(&mut fh); let mut src = IOBinarySource::new(&mut fh);
let mut r = src.packed_iovalues();
while let Some(v) = r.next(true).unwrap() { while let Some(v) = r.next(true).unwrap() {
vs.push(v); vs.push(v);
} }
b.iter_with_large_drop(|| { b.iter_with_large_drop(|| {
let mut bs = vec![]; let mut bs = vec![];
let mut w = PackedWriter::new(&mut bs); let mut w = PackedWriter::new(&mut bs);
let mut enc = IOValueDomainCodec;
for v in &vs { for v in &vs {
w.write(&v).unwrap(); w.write(&mut enc, v).unwrap();
} }
bs bs
}) })

View File

@ -1,7 +1,7 @@
use preserves::{de, value::{self, Reader, IOBinarySource, BinarySource}}; use preserves::{de, value::{self, Reader, IOBinarySource, BinarySource}};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use std::fs::File; use std::fs::File;
use std::io::Error; use std::io;
#[derive(Debug, Serialize, Deserialize, PartialEq)] #[derive(Debug, Serialize, Deserialize, PartialEq)]
enum Fruit { enum Fruit {
@ -32,7 +32,7 @@ enum Variety {
Anjou, Anjou,
} }
fn try_file(kind: &str, path: &str) -> Result<(), Error> { fn try_file(kind: &str, path: &str) -> io::Result<()> {
let fruits_value = IOBinarySource::new(&mut File::open(path)?).packed_iovalues().demand_next(true)?; let fruits_value = IOBinarySource::new(&mut File::open(path)?).packed_iovalues().demand_next(true)?;
println!("{:?}", fruits_value); println!("{:?}", fruits_value);
@ -46,7 +46,7 @@ fn try_file(kind: &str, path: &str) -> Result<(), Error> {
Ok(()) Ok(())
} }
fn main() -> Result<(), Error> { fn main() -> io::Result<()> {
try_file("KNOWN", "examples/known-data.bin")?; try_file("KNOWN", "examples/known-data.bin")?;
try_file("UNKNOWN", "examples/unknown-data.bin")?; try_file("UNKNOWN", "examples/unknown-data.bin")?;
Ok(()) Ok(())

View File

@ -1,9 +1,10 @@
use num::bigint::BigInt; use num::bigint::BigInt;
use std::convert::From; use std::convert::From;
use std::io;
#[derive(Debug)] #[derive(Debug)]
pub enum Error { pub enum Error {
Io(std::io::Error), Io(io::Error),
Message(String), Message(String),
InvalidUnicodeScalar(u32), InvalidUnicodeScalar(u32),
NumberOutOfRange(BigInt), NumberOutOfRange(BigInt),
@ -48,18 +49,18 @@ pub enum ExpectedKind {
UnicodeScalar, UnicodeScalar,
} }
impl From<std::io::Error> for Error { impl From<io::Error> for Error {
fn from(e: std::io::Error) -> Self { fn from(e: io::Error) -> Self {
Error::Io(e) Error::Io(e)
} }
} }
impl From<Error> for std::io::Error { impl From<Error> for io::Error {
fn from(e: Error) -> Self { fn from(e: Error) -> Self {
match e { match e {
Error::Io(ioe) => ioe, Error::Io(ioe) => ioe,
Error::Message(str) => std::io::Error::new(std::io::ErrorKind::Other, str), Error::Message(str) => io::Error::new(io::ErrorKind::Other, str),
_ => std::io::Error::new(std::io::ErrorKind::Other, e.to_string()), _ => io::Error::new(io::ErrorKind::Other, e.to_string()),
} }
} }
} }
@ -116,18 +117,18 @@ pub fn is_syntax_error(e: &Error) -> bool {
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
pub fn io_eof() -> std::io::Error { pub fn io_eof() -> io::Error {
std::io::Error::new(std::io::ErrorKind::UnexpectedEof, "EOF") io::Error::new(io::ErrorKind::UnexpectedEof, "EOF")
} }
pub fn is_eof_io_error(e: &std::io::Error) -> bool { pub fn is_eof_io_error(e: &io::Error) -> bool {
matches!(e.kind(), std::io::ErrorKind::UnexpectedEof) matches!(e.kind(), io::ErrorKind::UnexpectedEof)
} }
pub fn io_syntax_error(s: &str) -> std::io::Error { pub fn io_syntax_error(s: &str) -> io::Error {
std::io::Error::new(std::io::ErrorKind::InvalidData, s) io::Error::new(io::ErrorKind::InvalidData, s)
} }
pub fn is_syntax_io_error(e: &std::io::Error) -> bool { pub fn is_syntax_io_error(e: &io::Error) -> bool {
matches!(e.kind(), std::io::ErrorKind::InvalidData) matches!(e.kind(), io::ErrorKind::InvalidData)
} }

View File

@ -53,7 +53,7 @@ impl<D: Embeddable> DomainDecode<D> for NoEmbeddedDomainCodec {
_src: &'src mut S, _src: &'src mut S,
_read_annotations: bool, _read_annotations: bool,
) -> io::Result<D> { ) -> io::Result<D> {
Err(std::io::Error::new(std::io::ErrorKind::Unsupported, "Embedded values not supported here")) Err(io::Error::new(io::ErrorKind::Unsupported, "Embedded values not supported here"))
} }
} }
@ -63,6 +63,6 @@ impl<D: Embeddable> DomainEncode<D> for NoEmbeddedDomainCodec {
_w: &mut W, _w: &mut W,
_d: &D, _d: &D,
) -> io::Result<()> { ) -> io::Result<()> {
Err(std::io::Error::new(std::io::ErrorKind::Unsupported, "Embedded values not supported here")) Err(io::Error::new(io::ErrorKind::Unsupported, "Embedded values not supported here"))
} }
} }

View File

@ -1,4 +1,5 @@
use std::convert::{TryFrom, From}; use std::convert::{TryFrom, From};
use std::io;
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum Tag { pub enum Tag {
@ -24,10 +25,9 @@ pub enum Tag {
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub struct InvalidTag(u8); pub struct InvalidTag(u8);
impl From<InvalidTag> for std::io::Error { impl From<InvalidTag> for io::Error {
fn from(v: InvalidTag) -> Self { fn from(v: InvalidTag) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidData, io::Error::new(io::ErrorKind::InvalidData, format!("Invalid Preserves tag {}", v.0))
format!("Invalid Preserves tag {}", v.0))
} }
} }

View File

@ -72,7 +72,7 @@ impl<T> DerefMut for Suspendable<T> {
} }
} }
pub struct PackedWriter<W: std::io::Write>(Suspendable<W>); pub struct PackedWriter<W: io::Write>(Suspendable<W>);
impl PackedWriter<Vec<u8>> { impl PackedWriter<Vec<u8>> {
pub fn encode<D: Embeddable, N: NestedValue<D>, Enc: DomainEncode<D>>( pub fn encode<D: Embeddable, N: NestedValue<D>, Enc: DomainEncode<D>>(
@ -85,12 +85,12 @@ impl PackedWriter<Vec<u8>> {
Ok(buf) Ok(buf)
} }
pub fn encode_iovalue(v: &IOValue) -> std::io::Result<Vec<u8>> { pub fn encode_iovalue(v: &IOValue) -> io::Result<Vec<u8>> {
Self::encode(&mut IOValueDomainCodec, v) Self::encode(&mut IOValueDomainCodec, v)
} }
} }
impl<W: std::io::Write> PackedWriter<W> { impl<W: io::Write> PackedWriter<W> {
pub fn new(write: W) -> Self { pub fn new(write: W) -> Self {
PackedWriter(Suspendable::new(write)) PackedWriter(Suspendable::new(write))
} }
@ -171,7 +171,7 @@ pub trait WriteWriter: Writer {
} }
} }
impl<W: std::io::Write> WriteWriter for PackedWriter<W> { impl<W: io::Write> WriteWriter for PackedWriter<W> {
fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> { fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> {
self.w().write_all(v) self.w().write_all(v)
} }
@ -179,7 +179,7 @@ impl<W: std::io::Write> WriteWriter for PackedWriter<W> {
impl WriteWriter for BinaryOrderWriter { impl WriteWriter for BinaryOrderWriter {
fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> { fn write_raw_bytes(&mut self, v: &[u8]) -> io::Result<()> {
use std::io::Write; use io::Write;
self.buffer().write_all(v) self.buffer().write_all(v)
} }
} }
@ -194,7 +194,7 @@ impl<T: WriteWriter> AnnotationWriter for T {
} }
} }
impl<W: std::io::Write> CompoundWriter for PackedWriter<W> { impl<W: io::Write> CompoundWriter for PackedWriter<W> {
fn extend(&mut self) -> io::Result<()> { fn extend(&mut self) -> io::Result<()> {
Ok(()) Ok(())
} }
@ -301,7 +301,7 @@ macro_rules! fits_in_bytes {
}) })
} }
impl<W: std::io::Write> Writer for PackedWriter<W> impl<W: io::Write> Writer for PackedWriter<W>
{ {
type AnnWriter = Self; type AnnWriter = Self;
type SeqWriter = Self; type SeqWriter = Self;

View File

@ -2,7 +2,6 @@ use crate::error::{self, ExpectedKind, Received, io_eof};
use std::borrow::Cow; use std::borrow::Cow;
use std::io; use std::io;
use std::io::Read;
use std::marker::PhantomData; use std::marker::PhantomData;
use super::{DomainDecode, Embeddable, IOValue, IOValueDomainCodec, NestedValue}; use super::{DomainDecode, Embeddable, IOValue, IOValueDomainCodec, NestedValue};
@ -180,18 +179,18 @@ pub trait BinarySource<'de>: Sized {
} }
} }
pub struct IOBinarySource<'a, R: Read> { pub struct IOBinarySource<'a, R: io::Read> {
pub read: &'a mut R, pub read: &'a mut R,
pub buf: Option<u8>, pub buf: Option<u8>,
} }
impl<'a, R: Read> IOBinarySource<'a, R> { impl<'a, R: io::Read> IOBinarySource<'a, R> {
pub fn new(read: &'a mut R) -> Self { pub fn new(read: &'a mut R) -> Self {
IOBinarySource { read, buf: None } IOBinarySource { read, buf: None }
} }
} }
impl<'de, 'a, R: Read> BinarySource<'de> for IOBinarySource<'a, R> { impl<'de, 'a, R: io::Read> BinarySource<'de> for IOBinarySource<'a, R> {
fn skip(&mut self) -> io::Result<()> { fn skip(&mut self) -> io::Result<()> {
if self.buf.is_none() { unreachable!(); } if self.buf.is_none() { unreachable!(); }
self.buf = None; self.buf = None;

View File

@ -148,7 +148,7 @@ pub trait Writer: Sized {
} }
} }
pub fn varint<W: std::io::Write>(w: &mut W, mut v: u64) -> io::Result<usize> { pub fn varint<W: io::Write>(w: &mut W, mut v: u64) -> io::Result<usize> {
let mut byte_count = 0; let mut byte_count = 0;
loop { loop {
byte_count += 1; byte_count += 1;

View File

@ -8,15 +8,16 @@ use preserves::value::PackedWriter;
use preserves::value::Reader; use preserves::value::Reader;
use preserves::value::de::from_value as deserialize_from_value; use preserves::value::de::from_value as deserialize_from_value;
use std::iter::Iterator; use std::iter::Iterator;
use std::io;
mod samples; mod samples;
use samples::*; use samples::*;
fn decode_all(bytes: &'_ [u8]) -> Result<Vec<IOValue>, std::io::Error> { fn decode_all(bytes: &'_ [u8]) -> io::Result<Vec<IOValue>> {
BytesBinarySource::new(bytes).packed_iovalues().configured(true).collect() BytesBinarySource::new(bytes).packed_iovalues().configured(true).collect()
} }
#[test] fn run() -> std::io::Result<()> { #[test] fn run() -> io::Result<()> {
let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap(); let mut fh = std::fs::File::open("../../../tests/samples.bin").unwrap();
let mut src = IOBinarySource::new(&mut fh); let mut src = IOBinarySource::new(&mut fh);
let mut d = src.packed_iovalues().configured(true); let mut d = src.packed_iovalues().configured(true);