mirror of https://git.sr.ht/~stygianentity/bincode
moved the two designs into modules
This commit is contained in:
parent
9c6bf1aa41
commit
0cfb64511c
|
|
@ -2,6 +2,7 @@ extern crate bincode;
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize;
|
||||||
|
|
||||||
use bincode::SizeLimit;
|
use bincode::SizeLimit;
|
||||||
|
use bincode::rustc_serialize::{encode, decode};
|
||||||
|
|
||||||
#[derive(RustcEncodable, RustcDecodable, PartialEq)]
|
#[derive(RustcEncodable, RustcDecodable, PartialEq)]
|
||||||
struct Entity {
|
struct Entity {
|
||||||
|
|
@ -19,12 +20,12 @@ fn main() {
|
||||||
entities: vec![Entity {x: 0.0, y: 4.0}, Entity {x: 10.0, y: 20.5}]
|
entities: vec![Entity {x: 0.0, y: 4.0}, Entity {x: 10.0, y: 20.5}]
|
||||||
};
|
};
|
||||||
|
|
||||||
let encoded: Vec<u8> = bincode::encode(&world, SizeLimit::Infinite).unwrap();
|
let encoded: Vec<u8> = encode(&world, SizeLimit::Infinite).unwrap();
|
||||||
|
|
||||||
// 8 bytes for the length of the vector, 4 bytes per float.
|
// 8 bytes for the length of the vector, 4 bytes per float.
|
||||||
assert_eq!(encoded.len(), 8 + 4 * 4);
|
assert_eq!(encoded.len(), 8 + 4 * 4);
|
||||||
|
|
||||||
let decoded: World = bincode::decode(&encoded[..]).unwrap();
|
let decoded: World = decode(&encoded[..]).unwrap();
|
||||||
|
|
||||||
assert!(world == decoded);
|
assert!(world == decoded);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
125
src/lib.rs
125
src/lib.rs
|
|
@ -11,14 +11,15 @@
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! #![allow(unstable)]
|
//! #![allow(unstable)]
|
||||||
//! extern crate bincode;
|
//! extern crate bincode;
|
||||||
|
//! use bincode::rustc_serialize::{encode, decode};
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
//! // The object that we will serialize.
|
//! // The object that we will serialize.
|
||||||
//! let target = Some("hello world".to_string());
|
//! let target = Some("hello world".to_string());
|
||||||
//! // The maximum size of the encoded message.
|
//! // The maximum size of the encoded message.
|
||||||
//! let limit = bincode::SizeLimit::Bounded(20);
|
//! let limit = bincode::SizeLimit::Bounded(20);
|
||||||
//!
|
//!
|
||||||
//! let encoded: Vec<u8> = bincode::encode(&target, limit).unwrap();
|
//! let encoded: Vec<u8> = encode(&target, limit).unwrap();
|
||||||
//! let decoded: Option<String> = bincode::decode(&encoded[..]).unwrap();
|
//! let decoded: Option<String> = decode(&encoded[..]).unwrap();
|
||||||
//! assert_eq!(target, decoded);
|
//! assert_eq!(target, decoded);
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
|
|
@ -29,41 +30,17 @@
|
||||||
|
|
||||||
#![doc(html_logo_url = "./icon.png")]
|
#![doc(html_logo_url = "./icon.png")]
|
||||||
|
|
||||||
extern crate rustc_serialize;
|
extern crate rustc_serialize as rustc_serialize_crate;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate num;
|
extern crate num;
|
||||||
extern crate serde;
|
extern crate serde as serde_crate;
|
||||||
|
|
||||||
use rustc_serialize::{Encodable, Decodable};
|
|
||||||
|
|
||||||
pub use refbox::{RefBox, StrBox, SliceBox};
|
pub use refbox::{RefBox, StrBox, SliceBox};
|
||||||
pub use writer::{EncoderWriter, EncodingResult, EncodingError};
|
|
||||||
pub use reader::{DecoderReader, DecodingResult, DecodingError};
|
|
||||||
use writer::SizeChecker;
|
|
||||||
pub use reader_serde::{
|
|
||||||
Deserializer,
|
|
||||||
DeserializeResult,
|
|
||||||
DeserializeError,
|
|
||||||
from_reader,
|
|
||||||
from_slice,
|
|
||||||
};
|
|
||||||
pub use writer_serde::{
|
|
||||||
Serializer,
|
|
||||||
SerializeResult,
|
|
||||||
SerializeError,
|
|
||||||
to_writer,
|
|
||||||
to_vec,
|
|
||||||
serialized_size,
|
|
||||||
serialized_size_bounded,
|
|
||||||
};
|
|
||||||
|
|
||||||
use std::io::{Write, Read};
|
|
||||||
|
|
||||||
mod writer;
|
|
||||||
mod reader;
|
|
||||||
mod refbox;
|
mod refbox;
|
||||||
mod writer_serde;
|
pub mod rustc_serialize;
|
||||||
mod reader_serde;
|
pub mod serde;
|
||||||
|
|
||||||
/// A limit on the amount of bytes that can be read or written.
|
/// A limit on the amount of bytes that can be read or written.
|
||||||
///
|
///
|
||||||
|
|
@ -89,91 +66,3 @@ pub enum SizeLimit {
|
||||||
Bounded(u64)
|
Bounded(u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Encodes an encodable object into a `Vec` of bytes.
|
|
||||||
///
|
|
||||||
/// If the encoding would take more bytes than allowed by `size_limit`,
|
|
||||||
/// an error is returned.
|
|
||||||
pub fn encode<T: Encodable>(t: &T, size_limit: SizeLimit) -> EncodingResult<Vec<u8>> {
|
|
||||||
// Since we are putting values directly into a vector, we can do size
|
|
||||||
// computation out here and pre-allocate a buffer of *exactly*
|
|
||||||
// the right size.
|
|
||||||
let mut w = if let SizeLimit::Bounded(l) = size_limit {
|
|
||||||
let actual_size = encoded_size_bounded(t, l);
|
|
||||||
let actual_size = try!(actual_size.ok_or(EncodingError::SizeLimit));
|
|
||||||
Vec::with_capacity(actual_size as usize)
|
|
||||||
} else {
|
|
||||||
vec![]
|
|
||||||
};
|
|
||||||
|
|
||||||
match encode_into(t, &mut w, SizeLimit::Infinite) {
|
|
||||||
Ok(()) => Ok(w),
|
|
||||||
Err(e) => Err(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decodes a slice of bytes into an object.
|
|
||||||
///
|
|
||||||
/// This method does not have a size-limit because if you already have the bytes
|
|
||||||
/// in memory, then you don't gain anything by having a limiter.
|
|
||||||
pub fn decode<T: Decodable>(b: &[u8]) -> DecodingResult<T> {
|
|
||||||
let mut b = b;
|
|
||||||
decode_from(&mut b, SizeLimit::Infinite)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encodes an object directly into a `Writer`.
|
|
||||||
///
|
|
||||||
/// If the encoding would take more bytes than allowed by `size_limit`, an error
|
|
||||||
/// is returned and *no bytes* will be written into the `Writer`.
|
|
||||||
///
|
|
||||||
/// If this returns an `EncodingError` (other than SizeLimit), assume that the
|
|
||||||
/// writer is in an invalid state, as writing could bail out in the middle of
|
|
||||||
/// encoding.
|
|
||||||
pub fn encode_into<T: Encodable, W: Write>(t: &T,
|
|
||||||
w: &mut W,
|
|
||||||
size_limit: SizeLimit)
|
|
||||||
-> EncodingResult<()> {
|
|
||||||
try!(match size_limit {
|
|
||||||
SizeLimit::Infinite => Ok(()),
|
|
||||||
SizeLimit::Bounded(x) => {
|
|
||||||
let mut size_checker = SizeChecker::new(x);
|
|
||||||
t.encode(&mut size_checker)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
t.encode(&mut writer::EncoderWriter::new(w))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Decoes an object directly from a `Buffer`ed Reader.
|
|
||||||
///
|
|
||||||
/// If the provided `SizeLimit` is reached, the decode will bail immediately.
|
|
||||||
/// A SizeLimit can help prevent an attacker from flooding your server with
|
|
||||||
/// a neverending stream of values that runs your server out of memory.
|
|
||||||
///
|
|
||||||
/// If this returns an `DecodingError`, 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 decode_from<R: Read, T: Decodable>(r: &mut R, size_limit: SizeLimit) -> DecodingResult<T> {
|
|
||||||
Decodable::decode(&mut reader::DecoderReader::new(r, size_limit))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Returns the size that an object would be if encoded using bincode.
|
|
||||||
///
|
|
||||||
/// This is used internally as part of the check for encode_into, but it can
|
|
||||||
/// be useful for preallocating buffers if thats your style.
|
|
||||||
pub fn encoded_size<T: Encodable>(t: &T) -> u64 {
|
|
||||||
use std::u64::MAX;
|
|
||||||
let mut size_checker = SizeChecker::new(MAX);
|
|
||||||
t.encode(&mut size_checker).ok();
|
|
||||||
size_checker.written
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a maximum size limit, check how large an object would be if it
|
|
||||||
/// were to be encoded.
|
|
||||||
///
|
|
||||||
/// If it can be encoded in `max` or fewer bytes, that number will be returned
|
|
||||||
/// inside `Some`. If it goes over bounds, then None is returned.
|
|
||||||
pub fn encoded_size_bounded<T: Encodable>(t: &T, max: u64) -> Option<u64> {
|
|
||||||
let mut size_checker = SizeChecker::new(max);
|
|
||||||
t.encode(&mut size_checker).ok().map(|_| size_checker.written)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use rustc_serialize::{Encodable, Encoder};
|
use rustc_serialize_crate::{Encodable, Encoder, Decodable, Decoder};
|
||||||
use rustc_serialize::{Decodable, Decoder};
|
|
||||||
|
|
||||||
use serde;
|
use serde_crate as serde;
|
||||||
|
|
||||||
/// A struct for encoding nested reference types.
|
/// A struct for encoding nested reference types.
|
||||||
///
|
///
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,99 @@
|
||||||
|
use rustc_serialize_crate::{Encodable, Decodable};
|
||||||
|
use std::io::{Write, Read};
|
||||||
|
use ::SizeLimit;
|
||||||
|
|
||||||
|
pub use self::writer::{SizeChecker, EncoderWriter, EncodingResult, EncodingError};
|
||||||
|
pub use self::reader::{DecoderReader, DecodingResult, DecodingError};
|
||||||
|
|
||||||
|
mod reader;
|
||||||
|
mod writer;
|
||||||
|
|
||||||
|
/// Encodes an encodable object into a `Vec` of bytes.
|
||||||
|
///
|
||||||
|
/// If the encoding would take more bytes than allowed by `size_limit`,
|
||||||
|
/// an error is returned.
|
||||||
|
pub fn encode<T: Encodable>(t: &T, size_limit: SizeLimit) -> EncodingResult<Vec<u8>> {
|
||||||
|
// Since we are putting values directly into a vector, we can do size
|
||||||
|
// computation out here and pre-allocate a buffer of *exactly*
|
||||||
|
// the right size.
|
||||||
|
let mut w = if let SizeLimit::Bounded(l) = size_limit {
|
||||||
|
let actual_size = encoded_size_bounded(t, l);
|
||||||
|
let actual_size = try!(actual_size.ok_or(EncodingError::SizeLimit));
|
||||||
|
Vec::with_capacity(actual_size as usize)
|
||||||
|
} else {
|
||||||
|
vec![]
|
||||||
|
};
|
||||||
|
|
||||||
|
match encode_into(t, &mut w, SizeLimit::Infinite) {
|
||||||
|
Ok(()) => Ok(w),
|
||||||
|
Err(e) => Err(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decodes a slice of bytes into an object.
|
||||||
|
///
|
||||||
|
/// This method does not have a size-limit because if you already have the bytes
|
||||||
|
/// in memory, then you don't gain anything by having a limiter.
|
||||||
|
pub fn decode<T: Decodable>(b: &[u8]) -> DecodingResult<T> {
|
||||||
|
let mut b = b;
|
||||||
|
decode_from(&mut b, SizeLimit::Infinite)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encodes an object directly into a `Writer`.
|
||||||
|
///
|
||||||
|
/// If the encoding would take more bytes than allowed by `size_limit`, an error
|
||||||
|
/// is returned and *no bytes* will be written into the `Writer`.
|
||||||
|
///
|
||||||
|
/// If this returns an `EncodingError` (other than SizeLimit), assume that the
|
||||||
|
/// writer is in an invalid state, as writing could bail out in the middle of
|
||||||
|
/// encoding.
|
||||||
|
pub fn encode_into<T: Encodable, W: Write>(t: &T,
|
||||||
|
w: &mut W,
|
||||||
|
size_limit: SizeLimit)
|
||||||
|
-> EncodingResult<()> {
|
||||||
|
try!(match size_limit {
|
||||||
|
SizeLimit::Infinite => Ok(()),
|
||||||
|
SizeLimit::Bounded(x) => {
|
||||||
|
let mut size_checker = SizeChecker::new(x);
|
||||||
|
t.encode(&mut size_checker)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
t.encode(&mut writer::EncoderWriter::new(w))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decoes an object directly from a `Buffer`ed Reader.
|
||||||
|
///
|
||||||
|
/// If the provided `SizeLimit` is reached, the decode will bail immediately.
|
||||||
|
/// A SizeLimit can help prevent an attacker from flooding your server with
|
||||||
|
/// a neverending stream of values that runs your server out of memory.
|
||||||
|
///
|
||||||
|
/// If this returns an `DecodingError`, 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 decode_from<R: Read, T: Decodable>(r: &mut R, size_limit: SizeLimit) -> DecodingResult<T> {
|
||||||
|
Decodable::decode(&mut reader::DecoderReader::new(r, size_limit))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Returns the size that an object would be if encoded using bincode.
|
||||||
|
///
|
||||||
|
/// This is used internally as part of the check for encode_into, but it can
|
||||||
|
/// be useful for preallocating buffers if thats your style.
|
||||||
|
pub fn encoded_size<T: Encodable>(t: &T) -> u64 {
|
||||||
|
use std::u64::MAX;
|
||||||
|
let mut size_checker = SizeChecker::new(MAX);
|
||||||
|
t.encode(&mut size_checker).ok();
|
||||||
|
size_checker.written
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a maximum size limit, check how large an object would be if it
|
||||||
|
/// were to be encoded.
|
||||||
|
///
|
||||||
|
/// If it can be encoded in `max` or fewer bytes, that number will be returned
|
||||||
|
/// inside `Some`. If it goes over bounds, then None is returned.
|
||||||
|
pub fn encoded_size_bounded<T: Encodable>(t: &T, max: u64) -> Option<u64> {
|
||||||
|
let mut size_checker = SizeChecker::new(max);
|
||||||
|
t.encode(&mut size_checker).ok().map(|_| size_checker.written)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -4,11 +4,11 @@ use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::convert::From;
|
use std::convert::From;
|
||||||
|
|
||||||
use rustc_serialize::Decoder;
|
use rustc_serialize_crate::Decoder;
|
||||||
|
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
use byteorder::Error as ByteOrderError;
|
use byteorder::Error as ByteOrderError;
|
||||||
use super::SizeLimit;
|
use ::SizeLimit;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct InvalidEncoding {
|
pub struct InvalidEncoding {
|
||||||
|
|
@ -4,7 +4,7 @@ use std::io::ErrorKind as IoErrorKind;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use rustc_serialize::Encoder;
|
use rustc_serialize_crate::Encoder;
|
||||||
|
|
||||||
use byteorder::{BigEndian, WriteBytesExt};
|
use byteorder::{BigEndian, WriteBytesExt};
|
||||||
use byteorder::Error as ByteOrderError;
|
use byteorder::Error as ByteOrderError;
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
use std::io::{Write, Read};
|
||||||
|
use ::SizeLimit;
|
||||||
|
|
||||||
|
pub use self::reader::{
|
||||||
|
Deserializer,
|
||||||
|
DeserializeResult,
|
||||||
|
DeserializeError,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub use self::writer::{
|
||||||
|
Serializer,
|
||||||
|
SerializeResult,
|
||||||
|
SerializeError,
|
||||||
|
};
|
||||||
|
|
||||||
|
use self::writer::SizeChecker;
|
||||||
|
|
||||||
|
use serde_crate as serde;
|
||||||
|
|
||||||
|
mod reader;
|
||||||
|
mod writer;
|
||||||
|
|
||||||
|
pub fn serialize_into<W, T>(writer: &mut W,
|
||||||
|
value: &T,
|
||||||
|
size_limit: SizeLimit) -> SerializeResult<()>
|
||||||
|
where W: Write,
|
||||||
|
T: serde::Serialize,
|
||||||
|
{
|
||||||
|
match size_limit {
|
||||||
|
SizeLimit::Infinite => { }
|
||||||
|
SizeLimit::Bounded(x) => {
|
||||||
|
let mut size_checker = SizeChecker::new(x);
|
||||||
|
try!(value.serialize(&mut size_checker))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut serializer = Serializer::new(writer);
|
||||||
|
serde::Serialize::serialize(value, &mut serializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn serialize<T>(value: &T, size_limit: SizeLimit) -> SerializeResult<Vec<u8>>
|
||||||
|
where T: serde::Serialize,
|
||||||
|
{
|
||||||
|
// Since we are putting values directly into a vector, we can do size
|
||||||
|
// computation out here and pre-allocate a buffer of *exactly*
|
||||||
|
// the right size.
|
||||||
|
let mut writer = match size_limit {
|
||||||
|
SizeLimit::Bounded(size_limit) => {
|
||||||
|
let actual_size = match serialized_size_bounded(value, size_limit) {
|
||||||
|
Some(actual_size) => actual_size,
|
||||||
|
None => { return Err(SerializeError::SizeLimit); }
|
||||||
|
};
|
||||||
|
Vec::with_capacity(actual_size as usize)
|
||||||
|
}
|
||||||
|
SizeLimit::Infinite => Vec::new()
|
||||||
|
};
|
||||||
|
|
||||||
|
try!(serialize_into(&mut writer, value, SizeLimit::Infinite));
|
||||||
|
Ok(writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size that an object would be if serialized using bincode.
|
||||||
|
///
|
||||||
|
/// This is used internally as part of the check for encode_into, but it can
|
||||||
|
/// be useful for preallocating buffers if thats your style.
|
||||||
|
pub fn serialized_size<T: serde::Serialize>(value: &T) -> u64 {
|
||||||
|
use std::u64::MAX;
|
||||||
|
let mut size_checker = SizeChecker::new(MAX);
|
||||||
|
value.serialize(&mut size_checker).ok();
|
||||||
|
size_checker.written
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Given a maximum size limit, check how large an object would be if it
|
||||||
|
/// were to be serialized.
|
||||||
|
///
|
||||||
|
/// If it can be serialized in `max` or fewer bytes, that number will be returned
|
||||||
|
/// inside `Some`. If it goes over bounds, then None is returned.
|
||||||
|
pub fn serialized_size_bounded<T: serde::Serialize>(value: &T, max: u64) -> Option<u64> {
|
||||||
|
let mut size_checker = SizeChecker::new(max);
|
||||||
|
value.serialize(&mut size_checker).ok().map(|_| size_checker.written)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize_from<R, T>(reader: &mut R, size_limit: SizeLimit) -> DeserializeResult<T>
|
||||||
|
where R: Read,
|
||||||
|
T: serde::Deserialize,
|
||||||
|
{
|
||||||
|
let mut deserializer = Deserializer::new(reader, size_limit);
|
||||||
|
serde::Deserialize::deserialize(&mut deserializer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deserialize<T>(bytes: &[u8]) -> DeserializeResult<T>
|
||||||
|
where T: serde::Deserialize,
|
||||||
|
{
|
||||||
|
let mut reader = bytes;
|
||||||
|
deserialize_from(&mut reader, SizeLimit::Infinite)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
use std::io;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::io::Error as IoError;
|
use std::io::Error as IoError;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
@ -8,10 +7,10 @@ use std::convert::From;
|
||||||
use byteorder::Error as ByteOrderError;
|
use byteorder::Error as ByteOrderError;
|
||||||
use byteorder::{BigEndian, ReadBytesExt};
|
use byteorder::{BigEndian, ReadBytesExt};
|
||||||
use num;
|
use num;
|
||||||
use serde;
|
use serde_crate as serde;
|
||||||
use serde::de::value::ValueDeserializer;
|
use serde_crate::de::value::ValueDeserializer;
|
||||||
|
|
||||||
use super::SizeLimit;
|
use ::SizeLimit;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Clone, Debug)]
|
#[derive(Eq, PartialEq, Clone, Debug)]
|
||||||
pub struct InvalidEncoding {
|
pub struct InvalidEncoding {
|
||||||
|
|
@ -96,7 +95,7 @@ impl From<ByteOrderError> for DeserializeError {
|
||||||
|
|
||||||
impl From<serde::de::value::Error> for DeserializeError {
|
impl From<serde::de::value::Error> for DeserializeError {
|
||||||
fn from(err: serde::de::value::Error) -> DeserializeError {
|
fn from(err: serde::de::value::Error) -> DeserializeError {
|
||||||
use serde::de::value::Error;
|
use serde_crate::de::value::Error;
|
||||||
|
|
||||||
match err {
|
match err {
|
||||||
Error::SyntaxError => DeserializeError::SyntaxError,
|
Error::SyntaxError => DeserializeError::SyntaxError,
|
||||||
|
|
@ -530,22 +529,6 @@ impl<'a, R: Read> serde::de::VariantVisitor for Deserializer<'a, R> {
|
||||||
serde::de::Deserializer::visit_tuple(self, fields.len(), visitor)
|
serde::de::Deserializer::visit_tuple(self, fields.len(), visitor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_reader<R, T>(reader: &mut R, size_limit: SizeLimit) -> DeserializeResult<T>
|
|
||||||
where R: io::Read,
|
|
||||||
T: serde::Deserialize,
|
|
||||||
{
|
|
||||||
let mut deserializer = Deserializer::new(reader, size_limit);
|
|
||||||
serde::Deserialize::deserialize(&mut deserializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_slice<T>(bytes: &[u8]) -> DeserializeResult<T>
|
|
||||||
where T: serde::Deserialize,
|
|
||||||
{
|
|
||||||
let mut reader = bytes;
|
|
||||||
from_reader(&mut reader, SizeLimit::Infinite)
|
|
||||||
}
|
|
||||||
|
|
||||||
static UTF8_CHAR_WIDTH: [u8; 256] = [
|
static UTF8_CHAR_WIDTH: [u8; 256] = [
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
|
||||||
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
|
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, // 0x1F
|
||||||
|
|
@ -4,15 +4,12 @@ use std::io::Error as IoError;
|
||||||
use std::io::ErrorKind as IoErrorKind;
|
use std::io::ErrorKind as IoErrorKind;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use std::u64;
|
|
||||||
|
|
||||||
use serde;
|
use serde_crate as serde;
|
||||||
|
|
||||||
use byteorder::{BigEndian, WriteBytesExt};
|
use byteorder::{BigEndian, WriteBytesExt};
|
||||||
use byteorder::Error as ByteOrderError;
|
use byteorder::Error as ByteOrderError;
|
||||||
|
|
||||||
use super::SizeLimit;
|
|
||||||
|
|
||||||
pub type SerializeResult<T> = Result<T, SerializeError>;
|
pub type SerializeResult<T> = Result<T, SerializeError>;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -261,13 +258,13 @@ impl<'a, W: Write> serde::Serializer for Serializer<'a, W> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SizeChecker {
|
pub struct SizeChecker {
|
||||||
size_limit: u64,
|
pub size_limit: u64,
|
||||||
written: u64
|
pub written: u64
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SizeChecker {
|
impl SizeChecker {
|
||||||
fn new(limit: u64) -> SizeChecker {
|
pub fn new(limit: u64) -> SizeChecker {
|
||||||
SizeChecker {
|
SizeChecker {
|
||||||
size_limit: limit,
|
size_limit: limit,
|
||||||
written: 0
|
written: 0
|
||||||
|
|
@ -463,62 +460,3 @@ impl serde::Serializer for SizeChecker {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn to_writer<W, T>(writer: &mut W,
|
|
||||||
value: &T,
|
|
||||||
size_limit: SizeLimit) -> SerializeResult<()>
|
|
||||||
where W: Write,
|
|
||||||
T: serde::Serialize,
|
|
||||||
{
|
|
||||||
match size_limit {
|
|
||||||
SizeLimit::Infinite => { }
|
|
||||||
SizeLimit::Bounded(x) => {
|
|
||||||
let mut size_checker = SizeChecker::new(x);
|
|
||||||
try!(value.serialize(&mut size_checker))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut serializer = Serializer::new(writer);
|
|
||||||
serde::Serialize::serialize(value, &mut serializer)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn to_vec<T>(value: &T, size_limit: SizeLimit) -> SerializeResult<Vec<u8>>
|
|
||||||
where T: serde::Serialize,
|
|
||||||
{
|
|
||||||
// Since we are putting values directly into a vector, we can do size
|
|
||||||
// computation out here and pre-allocate a buffer of *exactly*
|
|
||||||
// the right size.
|
|
||||||
let mut writer = match size_limit {
|
|
||||||
SizeLimit::Bounded(size_limit) => {
|
|
||||||
let actual_size = match serialized_size_bounded(value, size_limit) {
|
|
||||||
Some(actual_size) => actual_size,
|
|
||||||
None => { return Err(SerializeError::SizeLimit); }
|
|
||||||
};
|
|
||||||
Vec::with_capacity(actual_size as usize)
|
|
||||||
}
|
|
||||||
SizeLimit::Infinite => Vec::new()
|
|
||||||
};
|
|
||||||
|
|
||||||
try!(to_writer(&mut writer, value, SizeLimit::Infinite));
|
|
||||||
Ok(writer)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the size that an object would be if serialized using bincode.
|
|
||||||
///
|
|
||||||
/// This is used internally as part of the check for encode_into, but it can
|
|
||||||
/// be useful for preallocating buffers if thats your style.
|
|
||||||
pub fn serialized_size<T: serde::Serialize>(value: &T) -> u64 {
|
|
||||||
let mut size_checker = SizeChecker::new(u64::MAX);
|
|
||||||
value.serialize(&mut size_checker).ok();
|
|
||||||
size_checker.written
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given a maximum size limit, check how large an object would be if it
|
|
||||||
/// were to be serialized.
|
|
||||||
///
|
|
||||||
/// If it can be serialized in `max` or fewer bytes, that number will be returned
|
|
||||||
/// inside `Some`. If it goes over bounds, then None is returned.
|
|
||||||
pub fn serialized_size_bounded<T: serde::Serialize>(value: &T, max: u64) -> Option<u64> {
|
|
||||||
let mut size_checker = SizeChecker::new(max);
|
|
||||||
value.serialize(&mut size_checker).ok().map(|_| size_checker.written)
|
|
||||||
}
|
|
||||||
106
tests/test.rs
106
tests/test.rs
|
|
@ -11,27 +11,17 @@ use std::ops::Deref;
|
||||||
|
|
||||||
use rustc_serialize::{Encoder, Decoder, Encodable, Decodable};
|
use rustc_serialize::{Encoder, Decoder, Encodable, Decodable};
|
||||||
|
|
||||||
use bincode::{
|
use bincode::{RefBox, StrBox, SliceBox};
|
||||||
encode,
|
|
||||||
decode,
|
|
||||||
decode_from,
|
|
||||||
encoded_size,
|
|
||||||
DecodingError,
|
|
||||||
DecodingResult,
|
|
||||||
DeserializeError,
|
|
||||||
DeserializeResult,
|
|
||||||
RefBox,
|
|
||||||
StrBox,
|
|
||||||
SliceBox,
|
|
||||||
};
|
|
||||||
|
|
||||||
use bincode::SizeLimit::{self, Infinite, Bounded};
|
use bincode::SizeLimit::{self, Infinite, Bounded};
|
||||||
|
use bincode::rustc_serialize::{encode, decode, decode_from, DecodingError};
|
||||||
|
use bincode::serde::{serialize, deserialize, deserialize_from, DeserializeError, DeserializeResult};
|
||||||
|
|
||||||
fn proxy_encode<V>(element: &V, size_limit: SizeLimit) -> Vec<u8>
|
fn proxy_encode<V>(element: &V, size_limit: SizeLimit) -> Vec<u8>
|
||||||
where V: Encodable + Decodable + serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
where V: Encodable + Decodable + serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
||||||
{
|
{
|
||||||
let v1 = bincode::encode(element, size_limit).unwrap();
|
let v1 = bincode::rustc_serialize::encode(element, size_limit).unwrap();
|
||||||
let v2 = bincode::to_vec(element, size_limit).unwrap();
|
let v2 = bincode::serde::serialize(element, size_limit).unwrap();
|
||||||
assert_eq!(v1, v2);
|
assert_eq!(v1, v2);
|
||||||
|
|
||||||
v1
|
v1
|
||||||
|
|
@ -40,8 +30,8 @@ fn proxy_encode<V>(element: &V, size_limit: SizeLimit) -> Vec<u8>
|
||||||
fn proxy_decode<V>(slice: &[u8]) -> V
|
fn proxy_decode<V>(slice: &[u8]) -> V
|
||||||
where V: Encodable + Decodable + serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
where V: Encodable + Decodable + serde::Serialize + serde::Deserialize + PartialEq + Debug + 'static
|
||||||
{
|
{
|
||||||
let e1 = bincode::decode(slice).unwrap();
|
let e1 = bincode::rustc_serialize::decode(slice).unwrap();
|
||||||
let e2 = bincode::from_slice(slice).unwrap();
|
let e2 = bincode::serde::deserialize(slice).unwrap();
|
||||||
|
|
||||||
assert_eq!(e1, e2);
|
assert_eq!(e1, e2);
|
||||||
|
|
||||||
|
|
@ -49,10 +39,10 @@ fn proxy_decode<V>(slice: &[u8]) -> V
|
||||||
}
|
}
|
||||||
|
|
||||||
fn proxy_encoded_size<V>(element: &V) -> u64
|
fn proxy_encoded_size<V>(element: &V) -> u64
|
||||||
where V: Encodable+Decodable+serde::Serialize+serde::Deserialize+PartialEq+Debug+'static
|
where V: Encodable + serde::Serialize + PartialEq + Debug + 'static
|
||||||
{
|
{
|
||||||
let ser_size = bincode::encoded_size(element);
|
let ser_size = bincode::rustc_serialize::encoded_size(element);
|
||||||
let serde_size = bincode::serialized_size(element);
|
let serde_size = bincode::serde::serialized_size(element);
|
||||||
assert_eq!(ser_size, serde_size);
|
assert_eq!(ser_size, serde_size);
|
||||||
ser_size
|
ser_size
|
||||||
}
|
}
|
||||||
|
|
@ -65,8 +55,8 @@ fn the_same<V>(element: V)
|
||||||
where V: Encodable + Decodable + PartialEq + Debug + 'static
|
where V: Encodable + Decodable + PartialEq + Debug + 'static
|
||||||
{
|
{
|
||||||
let rf = RefBox::new(v);
|
let rf = RefBox::new(v);
|
||||||
let encoded = encode(&rf, Infinite).unwrap();
|
let encoded = bincode::rustc_serialize::encode(&rf, Infinite).unwrap();
|
||||||
let decoded: RefBox<'static, V> = decode(&encoded[..]).unwrap();
|
let decoded: RefBox<'static, V> = bincode::rustc_serialize::decode(&encoded[..]).unwrap();
|
||||||
|
|
||||||
decoded.take().deref() == v
|
decoded.take().deref() == v
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +217,7 @@ fn test_unicode() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn decoding_errors() {
|
fn decoding_errors() {
|
||||||
fn isize_invalid_encoding<T>(res: DecodingResult<T>) {
|
fn isize_invalid_encoding<T>(res: bincode::rustc_serialize::DecodingResult<T>) {
|
||||||
match res {
|
match res {
|
||||||
Ok(_) => panic!("Expecting error"),
|
Ok(_) => panic!("Expecting error"),
|
||||||
Err(DecodingError::IoError(_)) => panic!("Expecting InvalidEncoding"),
|
Err(DecodingError::IoError(_)) => panic!("Expecting InvalidEncoding"),
|
||||||
|
|
@ -258,16 +248,16 @@ fn deserializing_errors() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
isize_invalid_deserialize(bincode::from_slice::<bool>(&vec![0xA][..]));
|
isize_invalid_deserialize(deserialize::<bool>(&vec![0xA][..]));
|
||||||
isize_invalid_deserialize(bincode::from_slice::<String>(&vec![0, 0, 0, 0, 0, 0, 0, 1, 0xFF][..]));
|
isize_invalid_deserialize(deserialize::<String>(&vec![0, 0, 0, 0, 0, 0, 0, 1, 0xFF][..]));
|
||||||
// Out-of-bounds variant
|
// Out-of-bounds variant
|
||||||
#[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, Debug)]
|
#[derive(RustcEncodable, RustcDecodable, Serialize, Deserialize, Debug)]
|
||||||
enum Test {
|
enum Test {
|
||||||
One,
|
One,
|
||||||
Two,
|
Two,
|
||||||
};
|
};
|
||||||
isize_invalid_deserialize(bincode::from_slice::<Test>(&vec![0, 0, 0, 5][..]));
|
isize_invalid_deserialize(deserialize::<Test>(&vec![0, 0, 0, 5][..]));
|
||||||
isize_invalid_deserialize(bincode::from_slice::<Option<u8>>(&vec![5, 0][..]));
|
isize_invalid_deserialize(deserialize::<Option<u8>>(&vec![5, 0][..]));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -284,11 +274,11 @@ fn too_big_decode() {
|
||||||
#[test]
|
#[test]
|
||||||
fn too_big_deserialize() {
|
fn too_big_deserialize() {
|
||||||
let serialized = vec![0,0,0,3];
|
let serialized = vec![0,0,0,3];
|
||||||
let deserialized: Result<u32, _> = bincode::from_reader(&mut &serialized[..], Bounded(3));
|
let deserialized: Result<u32, _> = deserialize_from(&mut &serialized[..], Bounded(3));
|
||||||
assert!(deserialized.is_err());
|
assert!(deserialized.is_err());
|
||||||
|
|
||||||
let serialized = vec![0,0,0,3];
|
let serialized = vec![0,0,0,3];
|
||||||
let deserialized: Result<u32, _> = bincode::from_reader(&mut &serialized[..], Bounded(4));
|
let deserialized: Result<u32, _> = deserialize_from(&mut &serialized[..], Bounded(4));
|
||||||
assert!(deserialized.is_ok());
|
assert!(deserialized.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -303,7 +293,7 @@ fn too_big_char_decode() {
|
||||||
#[test]
|
#[test]
|
||||||
fn too_big_char_deserialize() {
|
fn too_big_char_deserialize() {
|
||||||
let serialized = vec![0x41];
|
let serialized = vec![0x41];
|
||||||
let deserialized: Result<char, _> = bincode::from_reader(&mut &serialized[..], Bounded(1));
|
let deserialized: Result<char, _> = deserialize_from(&mut &serialized[..], Bounded(1));
|
||||||
assert!(deserialized.is_ok());
|
assert!(deserialized.is_ok());
|
||||||
assert_eq!(deserialized.unwrap(), 'A');
|
assert_eq!(deserialized.unwrap(), 'A');
|
||||||
}
|
}
|
||||||
|
|
@ -319,40 +309,40 @@ fn too_big_encode() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn too_big_serialize() {
|
fn too_big_serialize() {
|
||||||
assert!(bincode::to_vec(&0u32, Bounded(3)).is_err());
|
assert!(serialize(&0u32, Bounded(3)).is_err());
|
||||||
assert!(bincode::to_vec(&0u32, Bounded(4)).is_ok());
|
assert!(serialize(&0u32, Bounded(4)).is_ok());
|
||||||
|
|
||||||
assert!(bincode::to_vec(&"abcde", Bounded(8 + 4)).is_err());
|
assert!(serialize(&"abcde", Bounded(8 + 4)).is_err());
|
||||||
assert!(bincode::to_vec(&"abcde", Bounded(8 + 5)).is_ok());
|
assert!(serialize(&"abcde", Bounded(8 + 5)).is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_encoded_size() {
|
fn test_proxy_encoded_size() {
|
||||||
assert!(encoded_size(&0u8) == 1);
|
assert!(proxy_encoded_size(&0u8) == 1);
|
||||||
assert!(encoded_size(&0u16) == 2);
|
assert!(proxy_encoded_size(&0u16) == 2);
|
||||||
assert!(encoded_size(&0u32) == 4);
|
assert!(proxy_encoded_size(&0u32) == 4);
|
||||||
assert!(encoded_size(&0u64) == 8);
|
assert!(proxy_encoded_size(&0u64) == 8);
|
||||||
|
|
||||||
// length isize stored as u64
|
// length isize stored as u64
|
||||||
assert!(encoded_size(&"") == 8);
|
assert!(proxy_encoded_size(&"") == 8);
|
||||||
assert!(encoded_size(&"a") == 8 + 1);
|
assert!(proxy_encoded_size(&"a") == 8 + 1);
|
||||||
|
|
||||||
assert!(encoded_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
assert!(proxy_encoded_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialized_size() {
|
fn test_serialized_size() {
|
||||||
assert!(bincode::serialized_size(&0u8) == 1);
|
assert!(proxy_encoded_size(&0u8) == 1);
|
||||||
assert!(bincode::serialized_size(&0u16) == 2);
|
assert!(proxy_encoded_size(&0u16) == 2);
|
||||||
assert!(bincode::serialized_size(&0u32) == 4);
|
assert!(proxy_encoded_size(&0u32) == 4);
|
||||||
assert!(bincode::serialized_size(&0u64) == 8);
|
assert!(proxy_encoded_size(&0u64) == 8);
|
||||||
|
|
||||||
// length isize stored as u64
|
// length isize stored as u64
|
||||||
assert!(bincode::serialized_size(&"") == 8);
|
assert!(proxy_encoded_size(&"") == 8);
|
||||||
assert!(bincode::serialized_size(&"a") == 8 + 1);
|
assert!(proxy_encoded_size(&"a") == 8 + 1);
|
||||||
|
|
||||||
assert!(bincode::serialized_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
assert!(proxy_encoded_size(&vec![0u32, 1u32, 2u32]) == 8 + 3 * (4))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -411,8 +401,8 @@ fn test_refbox_serialize() {
|
||||||
|
|
||||||
// Test 1
|
// Test 1
|
||||||
{
|
{
|
||||||
let serialized = bincode::to_vec(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap();
|
let serialized = serialize(&Message::M1(RefBox::new(&large_object)), Infinite).unwrap();
|
||||||
let deserialized: Message<'static> = bincode::from_reader(&mut &serialized[..], Infinite).unwrap();
|
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||||
|
|
||||||
match deserialized {
|
match deserialized {
|
||||||
Message::M1(b) => assert!(b.take().deref() == &large_object),
|
Message::M1(b) => assert!(b.take().deref() == &large_object),
|
||||||
|
|
@ -422,8 +412,8 @@ fn test_refbox_serialize() {
|
||||||
|
|
||||||
// Test 2
|
// Test 2
|
||||||
{
|
{
|
||||||
let serialized = bincode::to_vec(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap();
|
let serialized = serialize(&Message::M2(RefBox::new(&large_map)), Infinite).unwrap();
|
||||||
let deserialized: Message<'static> = bincode::from_reader(&mut &serialized[..], Infinite).unwrap();
|
let deserialized: Message<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||||
|
|
||||||
match deserialized {
|
match deserialized {
|
||||||
Message::M2(b) => assert!(b.take().deref() == &large_map),
|
Message::M2(b) => assert!(b.take().deref() == &large_map),
|
||||||
|
|
@ -444,8 +434,8 @@ fn test_strbox_encode() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_strbox_serialize() {
|
fn test_strbox_serialize() {
|
||||||
let strx: &'static str = "hello world";
|
let strx: &'static str = "hello world";
|
||||||
let serialized = bincode::to_vec(&StrBox::new(strx), Infinite).unwrap();
|
let serialized = serialize(&StrBox::new(strx), Infinite).unwrap();
|
||||||
let deserialized: StrBox<'static> = bincode::from_reader(&mut &serialized[..], Infinite).unwrap();
|
let deserialized: StrBox<'static> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||||
let stringx: String = deserialized.take();
|
let stringx: String = deserialized.take();
|
||||||
assert!(strx == &stringx[..]);
|
assert!(strx == &stringx[..]);
|
||||||
}
|
}
|
||||||
|
|
@ -466,8 +456,8 @@ fn test_slicebox_encode() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_slicebox_serialize() {
|
fn test_slicebox_serialize() {
|
||||||
let slice = [1u32, 2, 3 ,4, 5];
|
let slice = [1u32, 2, 3 ,4, 5];
|
||||||
let serialized = bincode::to_vec(&SliceBox::new(&slice), Infinite).unwrap();
|
let serialized = serialize(&SliceBox::new(&slice), Infinite).unwrap();
|
||||||
let deserialized: SliceBox<'static, u32> = bincode::from_reader(&mut &serialized[..], Infinite).unwrap();
|
let deserialized: SliceBox<'static, u32> = deserialize_from(&mut &serialized[..], Infinite).unwrap();
|
||||||
{
|
{
|
||||||
let sb: &[u32] = &deserialized;
|
let sb: &[u32] = &deserialized;
|
||||||
assert!(slice == sb);
|
assert!(slice == sb);
|
||||||
|
|
@ -483,5 +473,5 @@ fn test_multi_strings_encode() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multi_strings_serialize() {
|
fn test_multi_strings_serialize() {
|
||||||
assert!(bincode::to_vec(&("foo", "bar", "baz"), Infinite).is_ok());
|
assert!(serialize(&("foo", "bar", "baz"), Infinite).is_ok());
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue