Merge branch 'master' of github.com:TyOverby/bincode

This commit is contained in:
Ty Overby 2017-10-10 16:29:00 -07:00
commit a094c215c4
7 changed files with 63 additions and 50 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "bincode" name = "bincode"
version = "0.8.0" version = "0.8.1"
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Daniel Griffen"] authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Daniel Griffen"]
repository = "https://github.com/TyOverby/bincode" repository = "https://github.com/TyOverby/bincode"
@ -12,7 +12,6 @@ description = "A binary serialization / deserialization strategy that uses Serde
[dependencies] [dependencies]
byteorder = "1.0.0" byteorder = "1.0.0"
num-traits = "0.1.32"
serde = "1.*.*" serde = "1.*.*"
[dev-dependencies] [dev-dependencies]

View File

@ -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 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. the object takes up in memory in a running Rust program.
In addition to exposing two simple functions that encode to Vec<u8> and decode In addition to exposing two simple functions
from Vec<u8>, binary-encode exposes a Reader/Writer API that makes it work (one that encodes to `Vec<u8>`, 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, perfectly with other stream-based apis such as rust files, network streams,
and the [flate2-rs](https://github.com/alexcrichton/flate2-rs) compression and the [flate2-rs](https://github.com/alexcrichton/flate2-rs) compression
library. library.
## [Api Documentation](http://tyoverby.github.io/bincode/bincode/) ## [Api Documentation](http://docs.rs/bincode/)
## Bincode in the wild ## Bincode in the wild
@ -32,13 +33,13 @@ extern crate bincode;
use bincode::{serialize, deserialize, Infinite}; use bincode::{serialize, deserialize, Infinite};
#[derive(Serialize, Deserialize, PartialEq)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Entity { struct Entity {
x: f32, x: f32,
y: f32, y: f32,
} }
#[derive(Serialize, Deserialize, PartialEq)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
struct World(Vec<Entity>); struct World(Vec<Entity>);
fn main() { fn main() {
@ -51,7 +52,7 @@ fn main() {
let decoded: World = deserialize(&encoded[..]).unwrap(); 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: However, there are some implementation details to be aware of:
* `isize`/`usize` are encoded as `i64`/`u64`, for portability. * `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. `u32` is enough for all practical uses.
* `str` is encoded as `(u64, &[u8])`, where the `u64` is the number of * `str` is encoded as `(u64, &[u8])`, where the `u64` is the number of
bytes contained in the encoded string. bytes contained in the encoded string.

View File

@ -4,13 +4,13 @@ extern crate bincode;
use bincode::{serialize, deserialize, Infinite}; use bincode::{serialize, deserialize, Infinite};
#[derive(Serialize, Deserialize, PartialEq)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Entity { struct Entity {
x: f32, x: f32,
y: f32, y: f32,
} }
#[derive(Serialize, Deserialize, PartialEq)] #[derive(Serialize, Deserialize, PartialEq, Debug)]
struct World(Vec<Entity>); struct World(Vec<Entity>);
fn main() { fn main() {
@ -18,10 +18,10 @@ fn main() {
let encoded: Vec<u8> = serialize(&world, Infinite).unwrap(); let encoded: Vec<u8> = 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); assert_eq!(encoded.len(), 8 + 4 * 4);
let decoded: World = deserialize(&encoded[..]).unwrap(); let decoded: World = deserialize(&encoded[..]).unwrap();
assert!(world == decoded); assert_eq!(world, decoded);
} }

View File

@ -85,7 +85,7 @@ where R: BincodeRead<'de>, S: SizeLimit, E: ByteOrder {
fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value> fn deserialize_any<V>(self, _visitor: V) -> Result<V::Value>
where V: serde::de::Visitor<'de>, 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)) Err(Error::custom(message))
} }

View File

@ -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 ::Result;
use serde_crate as serde; use serde_crate as serde;
/// A byte-oriented reading trait that is specialized for /// A byte-oriented reading trait that is specialized for
/// slices and generic readers. /// slices and generic readers.
pub trait BincodeRead<'storage>: IoRead { pub trait BincodeRead<'storage>: io::Read + ::private::Sealed {
#[doc(hidden)] #[doc(hidden)]
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value> fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where V: serde::de::Visitor<'storage>; where V: serde::de::Visitor<'storage>;
@ -23,7 +23,7 @@ pub struct SliceReader<'storage> {
} }
/// A BincodeRead implementation for io::Readers /// A BincodeRead implementation for io::Readers
pub struct IoReadReader<R> { pub struct IoReader<R> {
reader: R, reader: R,
temp_buffer: Vec<u8>, temp_buffer: Vec<u8>,
} }
@ -37,31 +37,37 @@ impl <'storage> SliceReader<'storage> {
} }
} }
impl <R> IoReadReader<R> { impl <R> IoReader<R> {
/// Constructs an IoReadReader /// Constructs an IoReadReader
pub fn new(r: R) -> IoReadReader<R> { pub fn new(r: R) -> IoReader<R> {
IoReadReader { IoReader {
reader: r, reader: r,
temp_buffer: vec![], temp_buffer: vec![],
} }
} }
} }
impl <'storage> IoRead for SliceReader<'storage> { impl <'storage> io::Read for SliceReader<'storage> {
fn read(&mut self, out: & mut [u8]) -> IoResult<usize> { fn read(&mut self, out: & mut [u8]) -> io::Result<usize> {
(&mut self.slice).read(out) (&mut self.slice).read(out)
} }
fn read_exact(&mut self, out: & mut [u8]) -> io::Result<()> {
(&mut self.slice).read_exact(out)
}
} }
impl <R: IoRead> IoRead for IoReadReader<R> { impl <R: io::Read> io::Read for IoReader<R> {
fn read(&mut self, out: & mut [u8]) -> IoResult<usize> { fn read(&mut self, out: & mut [u8]) -> io::Result<usize> {
self.reader.read(out) self.reader.read(out)
} }
fn read_exact(&mut self, out: & mut [u8]) -> io::Result<()> {
self.reader.read_exact(out)
}
} }
impl <'storage> SliceReader<'storage> { impl <'storage> SliceReader<'storage> {
fn unexpected_eof() -> Box<::ErrorKind> { 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 <R> IoReadReader<R> where R: IoRead { impl <R> IoReader<R> where R: io::Read {
fn fill_buffer(&mut self, length: usize) -> Result<()> { fn fill_buffer(&mut self, length: usize) -> Result<()> {
let current_length = self.temp_buffer.len(); let current_length = self.temp_buffer.len();
if length > current_length{ if length > current_length{
@ -120,7 +126,7 @@ impl <R> IoReadReader<R> where R: IoRead {
} }
} }
impl <R> BincodeRead<'static> for IoReadReader<R> where R: IoRead { impl <R> BincodeRead<'static> for IoReader<R> where R: io::Read {
fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value> fn forward_read_str<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where V: serde::de::Visitor<'static> { where V: serde::de::Visitor<'static> {
self.fill_buffer(length)?; self.fill_buffer(length)?;

View File

@ -2,10 +2,9 @@
//! that use the `serde` crate for the serializable and deserializable //! that use the `serde` crate for the serializable and deserializable
//! implementation. //! implementation.
use std::io::{Write, Read}; use std::io::{self, Write, Read};
use std::io::Error as IoError;
use std::{error, fmt, result}; use std::{error, fmt, result};
use ::SizeLimit; use ::{CountSize, SizeLimit};
use byteorder::{ByteOrder}; use byteorder::{ByteOrder};
pub use super::de::{ pub use super::de::{
@ -34,7 +33,7 @@ pub type Error = Box<ErrorKind>;
pub enum ErrorKind { pub enum ErrorKind {
/// If the error stems from the reader/writer that is being used /// If the error stems from the reader/writer that is being used
/// during (de)serialization, that error will be stored and returned here. /// 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 /// If the bytes in the reader are not decodable because of an invalid
/// encoding, this error will be returned. This error is only possible /// encoding, this error will be returned. This error is only possible
/// if a stream is corrupted. A stream produced from `encode` or `encode_into` /// 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 { impl error::Error for ErrorKind {
fn description(&self) -> &str { fn description(&self) -> &str {
match *self { match *self {
ErrorKind::IoError(ref err) => error::Error::description(err), ErrorKind::Io(ref err) => error::Error::description(err),
ErrorKind::InvalidEncoding{desc, ..} => desc, ErrorKind::InvalidEncoding{desc, ..} => desc,
ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences", ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences",
ErrorKind::SizeLimit => "the size limit for decoding has been reached", 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> { fn cause(&self) -> Option<&error::Error> {
match *self { match *self {
ErrorKind::IoError(ref err) => err.cause(), ErrorKind::Io(ref err) => Some(err),
ErrorKind::InvalidEncoding{..} => None, ErrorKind::InvalidEncoding{..} => None,
ErrorKind::SequenceMustHaveLength => None, ErrorKind::SequenceMustHaveLength => None,
ErrorKind::SizeLimit => None, ErrorKind::SizeLimit => None,
@ -77,17 +76,17 @@ impl error::Error for ErrorKind {
} }
} }
impl From<IoError> for Error { impl From<io::Error> for Error {
fn from(err: IoError) -> Error { fn from(err: io::Error) -> Error {
ErrorKind::IoError(err).into() ErrorKind::Io(err).into()
} }
} }
impl fmt::Display for ErrorKind { impl fmt::Display for ErrorKind {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
ErrorKind::IoError(ref ioerr) => ErrorKind::Io(ref ioerr) =>
write!(fmt, "IoError: {}", ioerr), write!(fmt, "Io: {}", ioerr),
ErrorKind::InvalidEncoding{desc, detail: None}=> ErrorKind::InvalidEncoding{desc, detail: None}=>
write!(fmt, "InvalidEncoding: {}", desc), write!(fmt, "InvalidEncoding: {}", desc),
ErrorKind::InvalidEncoding{desc, detail: Some(ref detail)}=> 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 /// 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 /// writer is in an invalid state, as writing could bail out in the middle of
/// serializing. /// serializing.
pub fn serialize_into<W: ?Sized, T: ?Sized, S, E>(writer: &mut W, value: &T, size_limit: S) -> Result<()> pub fn serialize_into<W, T: ?Sized, S, E>(writer: W, value: &T, size_limit: S) -> Result<()>
where W: Write, T: serde::Serialize, S: SizeLimit, E: ByteOrder where W: Write, T: serde::Serialize, S: SizeLimit, E: ByteOrder
{ {
if let Some(limit) = size_limit.limit() { if let Some(limit) = size_limit.limit() {
@ -155,12 +154,6 @@ pub fn serialize<T: ?Sized, S, E>(value: &T, size_limit: S) -> Result<Vec<u8>>
Ok(writer) Ok(writer)
} }
struct CountSize {
total: u64,
limit: Option<u64>,
}
impl SizeLimit for CountSize { impl SizeLimit for CountSize {
fn add(&mut self, c: u64) -> Result<()> { fn add(&mut self, c: u64) -> Result<()> {
self.total += c; self.total += c;
@ -219,10 +212,10 @@ pub fn serialized_size_bounded<T: ?Sized>(value: &T, max: u64) -> Option<u64>
/// If this returns an `Error`, assume that the buffer that you passed /// 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 is in an invalid state, as the error could be returned during any point
/// in the reading. /// in the reading.
pub fn deserialize_from<R: ?Sized, T, S, E>(reader: &mut R, size_limit: S) -> Result<T> pub fn deserialize_from<R, T, S, E>(reader: R, size_limit: S) -> Result<T>
where R: Read, T: serde::de::DeserializeOwned, S: SizeLimit, E: ByteOrder 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); let mut deserializer = Deserializer::<_, S, E>::new(reader, size_limit);
serde::Deserialize::deserialize(&mut deserializer) serde::Deserialize::deserialize(&mut deserializer)
} }

View File

@ -37,7 +37,6 @@
#![crate_type = "dylib"] #![crate_type = "dylib"]
extern crate byteorder; extern crate byteorder;
extern crate num_traits;
extern crate serde as serde_crate; extern crate serde as serde_crate;
mod ser; mod ser;
@ -46,7 +45,7 @@ pub mod internal;
pub mod read_types { pub mod read_types {
//! The types that the deserializer uses for optimizations //! 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}; use std::io::{Read, Write};
@ -125,7 +124,7 @@ pub fn serialize<T: ?Sized, S>(value: &T, size_limit: S) -> internal::Result<Vec
/// encoding function, the encoder will verify that the structure can be encoded /// encoding function, the encoder will verify that the structure can be encoded
/// within that limit. This verification occurs before any bytes are written to /// within that limit. This verification occurs before any bytes are written to
/// the Writer, so recovering from an error is easy. /// the Writer, so recovering from an error is easy.
pub trait SizeLimit { pub trait SizeLimit: private::Sealed {
/// Tells the SizeLimit that a certain number of bytes has been /// Tells the SizeLimit that a certain number of bytes has been
/// read or written. Returns Err if the limit has been exceeded. /// read or written. Returns Err if the limit has been exceeded.
fn add(&mut self, n: u64) -> Result<()>; fn add(&mut self, n: u64) -> Result<()>;
@ -143,6 +142,11 @@ pub struct Bounded(pub u64);
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
pub struct Infinite; pub struct Infinite;
struct CountSize {
total: u64,
limit: Option<u64>,
}
impl SizeLimit for Bounded { impl SizeLimit for Bounded {
#[inline(always)] #[inline(always)]
fn add(&mut self, n: u64) -> Result<()> { fn add(&mut self, n: u64) -> Result<()> {
@ -165,3 +169,13 @@ impl SizeLimit for Infinite {
#[inline(always)] #[inline(always)]
fn limit(&self) -> Option<u64> { None } fn limit(&self) -> Option<u64> { None }
} }
mod private {
pub trait Sealed {}
impl<'a> Sealed for super::de::read::SliceReader<'a> {}
impl<R> Sealed for super::de::read::IoReader<R> {}
impl Sealed for super::Infinite {}
impl Sealed for super::Bounded {}
impl Sealed for super::CountSize {}
}