diff --git a/Cargo.toml b/Cargo.toml index ddf68cb..77fb458 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bincode" -version = "0.8.0" +version = "0.8.1" authors = ["Ty Overby ", "Francesco Mazzoli ", "David Tolnay ", "Daniel Griffen"] repository = "https://github.com/TyOverby/bincode" @@ -12,7 +12,6 @@ description = "A binary serialization / deserialization strategy that uses Serde [dependencies] byteorder = "1.0.0" -num-traits = "0.1.32" serde = "1.*.*" [dev-dependencies] diff --git a/README.md b/README.md index b37d430..cbfff19 100644 --- a/README.md +++ b/README.md @@ -10,13 +10,14 @@ A compact encoder / decoder pair that uses a binary zero-fluff encoding scheme. The size of the encoded object will be the same or smaller than the size that the object takes up in memory in a running Rust program. -In addition to exposing two simple functions that encode to Vec and decode -from Vec, binary-encode exposes a Reader/Writer API that makes it work +In addition to exposing two simple functions +(one that encodes to `Vec`, and one that decodes from `&[u8]`), +binary-encode exposes a Reader/Writer API that makes it work perfectly with other stream-based apis such as rust files, network streams, and the [flate2-rs](https://github.com/alexcrichton/flate2-rs) compression library. -## [Api Documentation](http://tyoverby.github.io/bincode/bincode/) +## [Api Documentation](http://docs.rs/bincode/) ## Bincode in the wild @@ -32,13 +33,13 @@ extern crate bincode; use bincode::{serialize, deserialize, Infinite}; -#[derive(Serialize, Deserialize, PartialEq)] +#[derive(Serialize, Deserialize, PartialEq, Debug)] struct Entity { x: f32, y: f32, } -#[derive(Serialize, Deserialize, PartialEq)] +#[derive(Serialize, Deserialize, PartialEq, Debug)] struct World(Vec); fn main() { @@ -51,7 +52,7 @@ fn main() { let decoded: World = deserialize(&encoded[..]).unwrap(); - assert!(world == decoded); + assert_eq!(world, decoded); } ``` @@ -67,7 +68,7 @@ then the contents. However, there are some implementation details to be aware of: * `isize`/`usize` are encoded as `i64`/`u64`, for portability. -* enums variants are encoded as a `u32` instead of a `uint`. +* enums variants are encoded as a `u32` instead of a `usize`. `u32` is enough for all practical uses. * `str` is encoded as `(u64, &[u8])`, where the `u64` is the number of bytes contained in the encoded string. diff --git a/examples/basic.rs b/examples/basic.rs index 28c8b61..1632d75 100644 --- a/examples/basic.rs +++ b/examples/basic.rs @@ -4,13 +4,13 @@ extern crate bincode; use bincode::{serialize, deserialize, Infinite}; -#[derive(Serialize, Deserialize, PartialEq)] +#[derive(Serialize, Deserialize, PartialEq, Debug)] struct Entity { x: f32, y: f32, } -#[derive(Serialize, Deserialize, PartialEq)] +#[derive(Serialize, Deserialize, PartialEq, Debug)] struct World(Vec); fn main() { @@ -18,10 +18,10 @@ fn main() { let encoded: Vec = serialize(&world, Infinite).unwrap(); - // 8 bytes for the length of the vector, 4 bytes per float. + // 8 bytes for the length of the vector (usize), 4 bytes per float. assert_eq!(encoded.len(), 8 + 4 * 4); let decoded: World = deserialize(&encoded[..]).unwrap(); - assert!(world == decoded); + assert_eq!(world, decoded); } diff --git a/src/de/mod.rs b/src/de/mod.rs index b98be7e..ec3cb17 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -85,7 +85,7 @@ where R: BincodeRead<'de>, S: SizeLimit, E: ByteOrder { fn deserialize_any(self, _visitor: V) -> Result where V: serde::de::Visitor<'de>, { - let message = "bincode does not support Deserializer::deserialize"; + let message = "bincode does not support Deserializer::deserialize_any"; Err(Error::custom(message)) } diff --git a/src/de/read.rs b/src/de/read.rs index c22ee23..87aa304 100644 --- a/src/de/read.rs +++ b/src/de/read.rs @@ -1,10 +1,10 @@ -use std::io::{Read as IoRead, Result as IoResult, Error as IoError, ErrorKind as IoErrorKind}; +use std::io; use ::Result; use serde_crate as serde; /// A byte-oriented reading trait that is specialized for /// slices and generic readers. -pub trait BincodeRead<'storage>: IoRead { +pub trait BincodeRead<'storage>: io::Read + ::private::Sealed { #[doc(hidden)] fn forward_read_str(&mut self, length: usize, visitor: V) -> Result where V: serde::de::Visitor<'storage>; @@ -23,7 +23,7 @@ pub struct SliceReader<'storage> { } /// A BincodeRead implementation for io::Readers -pub struct IoReadReader { +pub struct IoReader { reader: R, temp_buffer: Vec, } @@ -37,31 +37,37 @@ impl <'storage> SliceReader<'storage> { } } -impl IoReadReader { +impl IoReader { /// Constructs an IoReadReader - pub fn new(r: R) -> IoReadReader { - IoReadReader { + pub fn new(r: R) -> IoReader { + IoReader { reader: r, temp_buffer: vec![], } } } -impl <'storage> IoRead for SliceReader<'storage> { - fn read(&mut self, out: & mut [u8]) -> IoResult { +impl <'storage> io::Read for SliceReader<'storage> { + fn read(&mut self, out: & mut [u8]) -> io::Result { (&mut self.slice).read(out) } + fn read_exact(&mut self, out: & mut [u8]) -> io::Result<()> { + (&mut self.slice).read_exact(out) + } } -impl IoRead for IoReadReader { - fn read(&mut self, out: & mut [u8]) -> IoResult { +impl io::Read for IoReader { + fn read(&mut self, out: & mut [u8]) -> io::Result { self.reader.read(out) } + fn read_exact(&mut self, out: & mut [u8]) -> io::Result<()> { + self.reader.read_exact(out) + } } impl <'storage> SliceReader<'storage> { fn unexpected_eof() -> Box<::ErrorKind> { - return Box::new(::ErrorKind::IoError(IoError::new(IoErrorKind::UnexpectedEof, ""))); + return Box::new(::ErrorKind::Io(io::Error::new(io::ErrorKind::UnexpectedEof, ""))); } } @@ -107,7 +113,7 @@ impl <'storage> BincodeRead<'storage> for SliceReader<'storage> { } } -impl IoReadReader where R: IoRead { +impl IoReader where R: io::Read { fn fill_buffer(&mut self, length: usize) -> Result<()> { let current_length = self.temp_buffer.len(); if length > current_length{ @@ -120,7 +126,7 @@ impl IoReadReader where R: IoRead { } } -impl BincodeRead<'static> for IoReadReader where R: IoRead { +impl BincodeRead<'static> for IoReader where R: io::Read { fn forward_read_str(&mut self, length: usize, visitor: V) -> Result where V: serde::de::Visitor<'static> { self.fill_buffer(length)?; diff --git a/src/internal.rs b/src/internal.rs index d8aa74e..78e4cfa 100644 --- a/src/internal.rs +++ b/src/internal.rs @@ -2,10 +2,9 @@ //! that use the `serde` crate for the serializable and deserializable //! implementation. -use std::io::{Write, Read}; -use std::io::Error as IoError; +use std::io::{self, Write, Read}; use std::{error, fmt, result}; -use ::SizeLimit; +use ::{CountSize, SizeLimit}; use byteorder::{ByteOrder}; pub use super::de::{ @@ -34,7 +33,7 @@ pub type Error = Box; pub enum ErrorKind { /// If the error stems from the reader/writer that is being used /// during (de)serialization, that error will be stored and returned here. - IoError(IoError), + Io(io::Error), /// If the bytes in the reader are not decodable because of an invalid /// encoding, this error will be returned. This error is only possible /// if a stream is corrupted. A stream produced from `encode` or `encode_into` @@ -57,7 +56,7 @@ pub enum ErrorKind { impl error::Error for ErrorKind { fn description(&self) -> &str { match *self { - ErrorKind::IoError(ref err) => error::Error::description(err), + ErrorKind::Io(ref err) => error::Error::description(err), ErrorKind::InvalidEncoding{desc, ..} => desc, ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences", ErrorKind::SizeLimit => "the size limit for decoding has been reached", @@ -68,7 +67,7 @@ impl error::Error for ErrorKind { fn cause(&self) -> Option<&error::Error> { match *self { - ErrorKind::IoError(ref err) => err.cause(), + ErrorKind::Io(ref err) => Some(err), ErrorKind::InvalidEncoding{..} => None, ErrorKind::SequenceMustHaveLength => None, ErrorKind::SizeLimit => None, @@ -77,17 +76,17 @@ impl error::Error for ErrorKind { } } -impl From for Error { - fn from(err: IoError) -> Error { - ErrorKind::IoError(err).into() +impl From for Error { + fn from(err: io::Error) -> Error { + ErrorKind::Io(err).into() } } impl fmt::Display for ErrorKind { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { match *self { - ErrorKind::IoError(ref ioerr) => - write!(fmt, "IoError: {}", ioerr), + ErrorKind::Io(ref ioerr) => + write!(fmt, "Io: {}", ioerr), ErrorKind::InvalidEncoding{desc, detail: None}=> write!(fmt, "InvalidEncoding: {}", desc), ErrorKind::InvalidEncoding{desc, detail: Some(ref detail)}=> @@ -122,7 +121,7 @@ impl serde::ser::Error for Error { /// If this returns an `Error` (other than SizeLimit), assume that the /// writer is in an invalid state, as writing could bail out in the middle of /// serializing. -pub fn serialize_into(writer: &mut W, value: &T, size_limit: S) -> Result<()> +pub fn serialize_into(writer: W, value: &T, size_limit: S) -> Result<()> where W: Write, T: serde::Serialize, S: SizeLimit, E: ByteOrder { if let Some(limit) = size_limit.limit() { @@ -155,12 +154,6 @@ pub fn serialize(value: &T, size_limit: S) -> Result> Ok(writer) } - -struct CountSize { - total: u64, - limit: Option, -} - impl SizeLimit for CountSize { fn add(&mut self, c: u64) -> Result<()> { self.total += c; @@ -219,10 +212,10 @@ pub fn serialized_size_bounded(value: &T, max: u64) -> Option /// If this returns an `Error`, assume that the buffer that you passed /// in is in an invalid state, as the error could be returned during any point /// in the reading. -pub fn deserialize_from(reader: &mut R, size_limit: S) -> Result +pub fn deserialize_from(reader: R, size_limit: S) -> Result where R: Read, T: serde::de::DeserializeOwned, S: SizeLimit, E: ByteOrder { - let reader = ::de::read::IoReadReader::new(reader); + let reader = ::de::read::IoReader::new(reader); let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit); serde::Deserialize::deserialize(&mut deserializer) } diff --git a/src/lib.rs b/src/lib.rs index f4d7681..c1c736b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,7 +37,6 @@ #![crate_type = "dylib"] extern crate byteorder; -extern crate num_traits; extern crate serde as serde_crate; mod ser; @@ -46,7 +45,7 @@ pub mod internal; pub mod read_types { //! The types that the deserializer uses for optimizations - pub use ::de::read::{SliceReader, BincodeRead, IoReadReader}; + pub use ::de::read::{SliceReader, BincodeRead, IoReader}; } use std::io::{Read, Write}; @@ -125,7 +124,7 @@ pub fn serialize(value: &T, size_limit: S) -> internal::Result Result<()>; @@ -143,6 +142,11 @@ pub struct Bounded(pub u64); #[derive(Copy, Clone)] pub struct Infinite; +struct CountSize { + total: u64, + limit: Option, +} + impl SizeLimit for Bounded { #[inline(always)] fn add(&mut self, n: u64) -> Result<()> { @@ -165,3 +169,13 @@ impl SizeLimit for Infinite { #[inline(always)] fn limit(&self) -> Option { None } } + +mod private { + pub trait Sealed {} + + impl<'a> Sealed for super::de::read::SliceReader<'a> {} + impl Sealed for super::de::read::IoReader {} + impl Sealed for super::Infinite {} + impl Sealed for super::Bounded {} + impl Sealed for super::CountSize {} +}