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]
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"]
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]

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 object takes up in memory in a running Rust program.
In addition to exposing two simple functions that encode to Vec<u8> and decode
from Vec<u8>, binary-encode exposes a Reader/Writer API that makes it work
In addition to exposing two simple functions
(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,
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<Entity>);
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.

View File

@ -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<Entity>);
fn main() {
@ -18,10 +18,10 @@ fn main() {
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);
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>
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))
}

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 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<V>(&mut self, length: usize, visitor: V) -> Result<V::Value>
where V: serde::de::Visitor<'storage>;
@ -23,7 +23,7 @@ pub struct SliceReader<'storage> {
}
/// A BincodeRead implementation for io::Readers
pub struct IoReadReader<R> {
pub struct IoReader<R> {
reader: R,
temp_buffer: Vec<u8>,
}
@ -37,31 +37,37 @@ impl <'storage> SliceReader<'storage> {
}
}
impl <R> IoReadReader<R> {
impl <R> IoReader<R> {
/// Constructs an IoReadReader
pub fn new(r: R) -> IoReadReader<R> {
IoReadReader {
pub fn new(r: R) -> IoReader<R> {
IoReader {
reader: r,
temp_buffer: vec![],
}
}
}
impl <'storage> IoRead for SliceReader<'storage> {
fn read(&mut self, out: & mut [u8]) -> IoResult<usize> {
impl <'storage> io::Read for SliceReader<'storage> {
fn read(&mut self, out: & mut [u8]) -> io::Result<usize> {
(&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> {
fn read(&mut self, out: & mut [u8]) -> IoResult<usize> {
impl <R: io::Read> io::Read for IoReader<R> {
fn read(&mut self, out: & mut [u8]) -> io::Result<usize> {
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 <R> IoReadReader<R> where R: IoRead {
impl <R> IoReader<R> 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 <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>
where V: serde::de::Visitor<'static> {
self.fill_buffer(length)?;

View File

@ -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<ErrorKind>;
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<IoError> for Error {
fn from(err: IoError) -> Error {
ErrorKind::IoError(err).into()
impl From<io::Error> 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<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
{
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)
}
struct CountSize {
total: u64,
limit: Option<u64>,
}
impl SizeLimit for CountSize {
fn add(&mut self, c: u64) -> Result<()> {
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
/// in is in an invalid state, as the error could be returned during any point
/// 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
{
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)
}

View File

@ -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<T: ?Sized, S>(value: &T, size_limit: S) -> internal::Result<Vec
/// encoding function, the encoder will verify that the structure can be encoded
/// within that limit. This verification occurs before any bytes are written to
/// 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
/// read or written. Returns Err if the limit has been exceeded.
fn add(&mut self, n: u64) -> Result<()>;
@ -143,6 +142,11 @@ pub struct Bounded(pub u64);
#[derive(Copy, Clone)]
pub struct Infinite;
struct CountSize {
total: u64,
limit: Option<u64>,
}
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<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 {}
}