mirror of https://git.sr.ht/~stygianentity/bincode
Merge branch 'master' of github.com:TyOverby/bincode
This commit is contained in:
commit
a094c215c4
|
|
@ -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]
|
||||
|
|
|
|||
15
README.md
15
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<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.
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)?;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
20
src/lib.rs
20
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<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 {}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue