mirror of https://git.sr.ht/~stygianentity/bincode
expose default options and serializers (#310)
Deprecate the old config system and make a refined version of the internal config system public. Doing allows the Serializer/Deserializer to be exposed since all of its generic type parameters are now public.
This commit is contained in:
parent
8839b0600d
commit
2355e48a7b
349
src/config.rs
349
src/config.rs
|
|
@ -1,64 +1,43 @@
|
||||||
use super::internal::{Bounded, Infinite, SizeLimit};
|
use byteorder;
|
||||||
use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
|
|
||||||
use de::read::BincodeRead;
|
use de::read::BincodeRead;
|
||||||
use error::Result;
|
use error::{ErrorKind, Result};
|
||||||
use serde;
|
use serde;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use {DeserializerAcceptor, SerializerAcceptor};
|
|
||||||
|
pub(crate) use self::internal::*;
|
||||||
|
|
||||||
use self::EndianOption::*;
|
use self::EndianOption::*;
|
||||||
use self::LimitOption::*;
|
use self::LimitOption::*;
|
||||||
|
|
||||||
struct DefaultOptions(Infinite);
|
/// The default options for bincode serialization/deserialization.
|
||||||
|
/// Implements OptionsExt to allow building configuration object for non-default settings.
|
||||||
pub(crate) trait Options {
|
///
|
||||||
type Limit: SizeLimit + 'static;
|
/// ### Defaults
|
||||||
type Endian: ByteOrder + 'static;
|
/// By default bincode will use little-endian encoding for mult-byte integers, and will not
|
||||||
|
/// limit the number of serialized/deserialized bytes.
|
||||||
fn limit(&mut self) -> &mut Self::Limit;
|
#[derive(Copy, Clone)]
|
||||||
}
|
pub struct DefaultOptions(Infinite);
|
||||||
|
|
||||||
pub(crate) trait OptionsExt: Options + Sized {
|
|
||||||
fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
|
|
||||||
WithOtherLimit::new(self, Infinite)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
|
|
||||||
WithOtherLimit::new(self, Bounded(limit))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
|
|
||||||
WithOtherEndian::new(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
|
|
||||||
WithOtherEndian::new(self)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
|
|
||||||
WithOtherEndian::new(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, O: Options> Options for &'a mut O {
|
|
||||||
type Limit = O::Limit;
|
|
||||||
type Endian = O::Endian;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn limit(&mut self) -> &mut Self::Limit {
|
|
||||||
(*self).limit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Options> OptionsExt for T {}
|
|
||||||
|
|
||||||
impl DefaultOptions {
|
impl DefaultOptions {
|
||||||
fn new() -> DefaultOptions {
|
/// Get a default configuration object.
|
||||||
|
///
|
||||||
|
/// ### Default Configuration:
|
||||||
|
///
|
||||||
|
/// | Byte limit | Endianness |
|
||||||
|
/// |------------|------------|
|
||||||
|
/// | Unlimited | Little |
|
||||||
|
pub fn new() -> DefaultOptions {
|
||||||
DefaultOptions(Infinite)
|
DefaultOptions(Infinite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for DefaultOptions {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Options for DefaultOptions {
|
impl Options for DefaultOptions {
|
||||||
type Limit = Infinite;
|
type Limit = Infinite;
|
||||||
type Endian = LittleEndian;
|
type Endian = LittleEndian;
|
||||||
|
|
@ -69,6 +48,211 @@ impl Options for DefaultOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A configuration builder trait whose options Bincode will use
|
||||||
|
/// while serializing and deserializing.
|
||||||
|
///
|
||||||
|
/// ### Options
|
||||||
|
/// Endianness: The endianness with which multi-byte integers will be read/written. *default: little endian*
|
||||||
|
///
|
||||||
|
/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
|
||||||
|
///
|
||||||
|
/// ### Byte Limit Details
|
||||||
|
/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
|
||||||
|
/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
|
||||||
|
///
|
||||||
|
/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
|
||||||
|
/// serialization that goes over the limit.
|
||||||
|
/// Sets the byte limit to be unlimited.
|
||||||
|
/// This is the default.
|
||||||
|
pub trait OptionsExt: Options + Sized {
|
||||||
|
/// Sets the byte limit to be unlimited.
|
||||||
|
/// This is the default.
|
||||||
|
fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
|
||||||
|
WithOtherLimit::new(self, Infinite)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the byte limit to `limit`.
|
||||||
|
fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
|
||||||
|
WithOtherLimit::new(self, Bounded(limit))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the endianness to little-endian
|
||||||
|
/// This is the default.
|
||||||
|
fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
|
||||||
|
WithOtherEndian::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the endianness to big-endian
|
||||||
|
fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
|
||||||
|
WithOtherEndian::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the endianness to the the machine-native endianness
|
||||||
|
fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
|
||||||
|
WithOtherEndian::new(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializes a serializable object into a `Vec` of bytes using this configuration
|
||||||
|
#[inline(always)]
|
||||||
|
fn serialize<S: ?Sized + serde::Serialize>(self, t: &S) -> Result<Vec<u8>> {
|
||||||
|
::internal::serialize(t, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the size that an object would be if serialized using Bincode with this configuration
|
||||||
|
#[inline(always)]
|
||||||
|
fn serialized_size<T: ?Sized + serde::Serialize>(self, t: &T) -> Result<u64> {
|
||||||
|
::internal::serialized_size(t, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Serializes an object directly into a `Writer` using this configuration
|
||||||
|
///
|
||||||
|
/// If the serialization would take more bytes than allowed by the size limit, an error
|
||||||
|
/// is returned and *no bytes* will be written into the `Writer`
|
||||||
|
#[inline(always)]
|
||||||
|
fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(self, w: W, t: &T) -> Result<()> {
|
||||||
|
::internal::serialize_into(w, t, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes a slice of bytes into an instance of `T` using this configuration
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize<'a, T: serde::Deserialize<'a>>(self, bytes: &'a [u8]) -> Result<T> {
|
||||||
|
::internal::deserialize(bytes, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// TODO: document
|
||||||
|
#[doc(hidden)]
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize_in_place<'a, R, T>(self, reader: R, place: &mut T) -> Result<()>
|
||||||
|
where
|
||||||
|
R: BincodeRead<'a>,
|
||||||
|
T: serde::de::Deserialize<'a>,
|
||||||
|
{
|
||||||
|
::internal::deserialize_in_place(reader, self, place)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes a slice of bytes with state `seed` using this configuration.
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
|
||||||
|
self,
|
||||||
|
seed: T,
|
||||||
|
bytes: &'a [u8],
|
||||||
|
) -> Result<T::Value> {
|
||||||
|
::internal::deserialize_seed(seed, bytes, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes an object directly from a `Read`er using this configuration
|
||||||
|
///
|
||||||
|
/// If this returns an `Error`, `reader` may be in an invalid state.
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(self, reader: R) -> Result<T> {
|
||||||
|
::internal::deserialize_from(reader, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes an object directly from a `Read`er with state `seed` using this configuration
|
||||||
|
///
|
||||||
|
/// If this returns an `Error`, `reader` may be in an invalid state.
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
|
||||||
|
self,
|
||||||
|
seed: T,
|
||||||
|
reader: R,
|
||||||
|
) -> Result<T::Value> {
|
||||||
|
::internal::deserialize_from_seed(seed, reader, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
|
||||||
|
/// It is highly recommended to use `deserialize_from` unless you need to implement
|
||||||
|
/// `BincodeRead` for performance reasons.
|
||||||
|
///
|
||||||
|
/// If this returns an `Error`, `reader` may be in an invalid state.
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
|
||||||
|
self,
|
||||||
|
reader: R,
|
||||||
|
) -> Result<T> {
|
||||||
|
::internal::deserialize_from_custom(reader, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
|
||||||
|
/// configuration. It is highly recommended to use `deserialize_from` unless you need to
|
||||||
|
/// implement `BincodeRead` for performance reasons.
|
||||||
|
///
|
||||||
|
/// If this returns an `Error`, `reader` may be in an invalid state.
|
||||||
|
#[inline(always)]
|
||||||
|
fn deserialize_from_custom_seed<'a, R: BincodeRead<'a>, T: serde::de::DeserializeSeed<'a>>(
|
||||||
|
self,
|
||||||
|
seed: T,
|
||||||
|
reader: R,
|
||||||
|
) -> Result<T::Value> {
|
||||||
|
::internal::deserialize_from_custom_seed(seed, reader, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Options> OptionsExt for T {}
|
||||||
|
|
||||||
|
/// A SizeLimit that restricts serialized or deserialized messages from
|
||||||
|
/// exceeding a certain byte length.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Bounded(pub u64);
|
||||||
|
|
||||||
|
/// A SizeLimit without a limit!
|
||||||
|
/// Use this if you don't care about the size of encoded or decoded messages.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct Infinite;
|
||||||
|
|
||||||
|
impl SizeLimit for Bounded {
|
||||||
|
#[inline(always)]
|
||||||
|
fn add(&mut self, n: u64) -> Result<()> {
|
||||||
|
if self.0 >= n {
|
||||||
|
self.0 -= n;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err(Box::new(ErrorKind::SizeLimit))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn limit(&self) -> Option<u64> {
|
||||||
|
Some(self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SizeLimit for Infinite {
|
||||||
|
#[inline(always)]
|
||||||
|
fn add(&mut self, _: u64) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn limit(&self) -> Option<u64> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Little-endian byte ordering.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct LittleEndian;
|
||||||
|
|
||||||
|
/// Big-endian byte ordering.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct BigEndian;
|
||||||
|
|
||||||
|
/// The native byte ordering of the current system.
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
pub struct NativeEndian;
|
||||||
|
|
||||||
|
impl BincodeByteOrder for LittleEndian {
|
||||||
|
type Endian = byteorder::LittleEndian;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BincodeByteOrder for BigEndian {
|
||||||
|
type Endian = byteorder::BigEndian;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BincodeByteOrder for NativeEndian {
|
||||||
|
type Endian = byteorder::NativeEndian;
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
enum LimitOption {
|
enum LimitOption {
|
||||||
Unlimited,
|
Unlimited,
|
||||||
|
|
@ -96,17 +280,25 @@ enum EndianOption {
|
||||||
/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
|
/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
|
||||||
/// serialization that goes over the limit.
|
/// serialization that goes over the limit.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
#[deprecated(
|
||||||
|
since = "1.3.0",
|
||||||
|
note = "please use the `DefaultOptions`/`OptionsExt` system instead"
|
||||||
|
)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
limit: LimitOption,
|
limit: LimitOption,
|
||||||
endian: EndianOption,
|
endian: EndianOption,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct WithOtherLimit<O: Options, L: SizeLimit> {
|
/// A configuration struct with a user-specified byte limit
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct WithOtherLimit<O: Options, L: SizeLimit> {
|
||||||
_options: O,
|
_options: O,
|
||||||
pub(crate) new_limit: L,
|
pub(crate) new_limit: L,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct WithOtherEndian<O: Options, E: ByteOrder> {
|
/// A configuration struct with a user-specified endian order
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub struct WithOtherEndian<O: Options, E: BincodeByteOrder> {
|
||||||
options: O,
|
options: O,
|
||||||
_endian: PhantomData<E>,
|
_endian: PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
@ -121,7 +313,7 @@ impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<O: Options, E: ByteOrder> WithOtherEndian<O, E> {
|
impl<O: Options, E: BincodeByteOrder> WithOtherEndian<O, E> {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
|
pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
|
||||||
WithOtherEndian {
|
WithOtherEndian {
|
||||||
|
|
@ -131,7 +323,7 @@ impl<O: Options, E: ByteOrder> WithOtherEndian<O, E> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<O: Options, E: ByteOrder + 'static> Options for WithOtherEndian<O, E> {
|
impl<O: Options, E: BincodeByteOrder + 'static> Options for WithOtherEndian<O, E> {
|
||||||
type Limit = O::Limit;
|
type Limit = O::Limit;
|
||||||
type Endian = E;
|
type Endian = E;
|
||||||
|
|
||||||
|
|
@ -333,32 +525,39 @@ impl Config {
|
||||||
) -> Result<T::Value> {
|
) -> Result<T::Value> {
|
||||||
config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
|
config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Executes the acceptor with a serde::Deserializer instance.
|
mod internal {
|
||||||
/// NOT A PART OF THE STABLE PUBLIC API
|
use super::*;
|
||||||
#[doc(hidden)]
|
use byteorder::ByteOrder;
|
||||||
pub fn with_deserializer<'a, A, R>(&self, reader: R, acceptor: A) -> A::Output
|
|
||||||
where
|
pub trait Options {
|
||||||
A: DeserializerAcceptor<'a>,
|
type Limit: SizeLimit + 'static;
|
||||||
R: BincodeRead<'a>,
|
type Endian: BincodeByteOrder + 'static;
|
||||||
{
|
|
||||||
config_map!(self, opts => {
|
fn limit(&mut self) -> &mut Self::Limit;
|
||||||
let mut deserializer = ::de::Deserializer::new(reader, opts);
|
|
||||||
acceptor.accept(&mut deserializer)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Executes the acceptor with a serde::Serializer instance.
|
impl<'a, O: Options> Options for &'a mut O {
|
||||||
/// NOT A PART OF THE STABLE PUBLIC API
|
type Limit = O::Limit;
|
||||||
#[doc(hidden)]
|
type Endian = O::Endian;
|
||||||
pub fn with_serializer<A, W>(&self, writer: W, acceptor: A) -> A::Output
|
|
||||||
where
|
#[inline(always)]
|
||||||
A: SerializerAcceptor,
|
fn limit(&mut self) -> &mut Self::Limit {
|
||||||
W: Write,
|
(*self).limit()
|
||||||
{
|
}
|
||||||
config_map!(self, opts => {
|
}
|
||||||
let mut serializer = ::ser::Serializer::new(writer, opts);
|
|
||||||
acceptor.accept(&mut serializer)
|
/// A trait for stopping serialization and deserialization when a certain limit has been reached.
|
||||||
})
|
pub trait SizeLimit {
|
||||||
|
/// 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<()>;
|
||||||
|
/// Returns the hard limit (if one exists)
|
||||||
|
fn limit(&self) -> Option<u64>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait BincodeByteOrder {
|
||||||
|
type Endian: ByteOrder + 'static;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,15 @@
|
||||||
use config::Options;
|
use config::{BincodeByteOrder, Options};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
use self::read::BincodeRead;
|
use self::read::{BincodeRead, IoReader, SliceReader};
|
||||||
use byteorder::ReadBytesExt;
|
use byteorder::ReadBytesExt;
|
||||||
use internal::SizeLimit;
|
use config::SizeLimit;
|
||||||
use serde;
|
use serde;
|
||||||
use serde::de::Error as DeError;
|
use serde::de::Error as DeError;
|
||||||
use serde::de::IntoDeserializer;
|
use serde::de::IntoDeserializer;
|
||||||
use {Error, ErrorKind, Result};
|
use {Error, ErrorKind, Result};
|
||||||
|
|
||||||
|
/// Specialized ways to read data into bincode.
|
||||||
pub mod read;
|
pub mod read;
|
||||||
|
|
||||||
/// A Deserializer that reads bytes from a buffer.
|
/// A Deserializer that reads bytes from a buffer.
|
||||||
|
|
@ -24,14 +25,30 @@ pub mod read;
|
||||||
/// serde::Deserialize::deserialize(&mut deserializer);
|
/// serde::Deserialize::deserialize(&mut deserializer);
|
||||||
/// let bytes_read = d.bytes_read();
|
/// let bytes_read = d.bytes_read();
|
||||||
/// ```
|
/// ```
|
||||||
pub(crate) struct Deserializer<R, O: Options> {
|
pub struct Deserializer<R, O: Options> {
|
||||||
reader: R,
|
reader: R,
|
||||||
options: O,
|
options: O,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
|
impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
|
||||||
/// Creates a new Deserializer with a given `Read`er and a size_limit.
|
/// Creates a new Deserializer with a given `Read`er and options.
|
||||||
pub(crate) fn new(r: R, options: O) -> Deserializer<R, O> {
|
pub fn with_reader<IR: Read>(r: IR, options: O) -> Deserializer<IoReader<IR>, O> {
|
||||||
|
Deserializer {
|
||||||
|
reader: IoReader::new(r),
|
||||||
|
options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new Deserializer that will read from the given slice.
|
||||||
|
pub fn from_slice(slice: &'de [u8], options: O) -> Deserializer<SliceReader<'de>, O> {
|
||||||
|
Deserializer {
|
||||||
|
reader: SliceReader::new(slice),
|
||||||
|
options,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new Deserializer with the given `BincodeRead`er
|
||||||
|
pub fn with_bincode_read(r: R, options: O) -> Deserializer<R, O> {
|
||||||
Deserializer { reader: r, options }
|
Deserializer { reader: r, options }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -63,7 +80,7 @@ macro_rules! impl_nums {
|
||||||
where V: serde::de::Visitor<'de>,
|
where V: serde::de::Visitor<'de>,
|
||||||
{
|
{
|
||||||
self.read_type::<$ty>()?;
|
self.read_type::<$ty>()?;
|
||||||
let value = self.reader.$reader_method::<O::Endian>()?;
|
let value = self.reader.$reader_method::<<O::Endian as BincodeByteOrder>::Endian>()?;
|
||||||
visitor.$visitor_method(value)
|
visitor.$visitor_method(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,15 +27,11 @@ pub trait BincodeRead<'storage>: io::Read {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A BincodeRead implementation for byte slices
|
/// A BincodeRead implementation for byte slices
|
||||||
/// NOT A PART OF THE STABLE PUBLIC API
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct SliceReader<'storage> {
|
pub struct SliceReader<'storage> {
|
||||||
slice: &'storage [u8],
|
slice: &'storage [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A BincodeRead implementation for io::Readers
|
/// A BincodeRead implementation for `io::Read`ers
|
||||||
/// NOT A PART OF THE STABLE PUBLIC API
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub struct IoReader<R> {
|
pub struct IoReader<R> {
|
||||||
reader: R,
|
reader: R,
|
||||||
temp_buffer: Vec<u8>,
|
temp_buffer: Vec<u8>,
|
||||||
|
|
@ -43,7 +39,7 @@ pub struct IoReader<R> {
|
||||||
|
|
||||||
impl<'storage> SliceReader<'storage> {
|
impl<'storage> SliceReader<'storage> {
|
||||||
/// Constructs a slice reader
|
/// Constructs a slice reader
|
||||||
pub fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
|
pub(crate) fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
|
||||||
SliceReader { slice: bytes }
|
SliceReader { slice: bytes }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,7 +56,7 @@ impl<'storage> SliceReader<'storage> {
|
||||||
|
|
||||||
impl<R> IoReader<R> {
|
impl<R> IoReader<R> {
|
||||||
/// Constructs an IoReadReader
|
/// Constructs an IoReadReader
|
||||||
pub fn new(r: R) -> IoReader<R> {
|
pub(crate) fn new(r: R) -> IoReader<R> {
|
||||||
IoReader {
|
IoReader {
|
||||||
reader: r,
|
reader: r,
|
||||||
temp_buffer: vec![],
|
temp_buffer: vec![],
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,9 @@ use serde;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
use config::{Options, OptionsExt};
|
use config::{Infinite, Options, OptionsExt, SizeLimit};
|
||||||
use de::read::BincodeRead;
|
use de::read::BincodeRead;
|
||||||
use {ErrorKind, Result};
|
use Result;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
struct CountSize<L: SizeLimit> {
|
|
||||||
total: u64,
|
|
||||||
other_limit: L,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn serialize_into<W, T: ?Sized, O>(writer: W, value: &T, mut options: O) -> Result<()>
|
pub(crate) fn serialize_into<W, T: ?Sized, O>(writer: W, value: &T, mut options: O) -> Result<()>
|
||||||
where
|
where
|
||||||
|
|
@ -42,35 +36,14 @@ where
|
||||||
Ok(writer)
|
Ok(writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<L: SizeLimit> SizeLimit for CountSize<L> {
|
pub(crate) fn serialized_size<T: ?Sized, O: Options>(value: &T, options: O) -> Result<u64>
|
||||||
fn add(&mut self, c: u64) -> Result<()> {
|
|
||||||
self.other_limit.add(c)?;
|
|
||||||
self.total += c;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn limit(&self) -> Option<u64> {
|
|
||||||
unreachable!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn serialized_size<T: ?Sized, O: Options>(value: &T, mut options: O) -> Result<u64>
|
|
||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
let old_limiter = options.limit().clone();
|
let mut size_counter = ::ser::SizeChecker { options, total: 0 };
|
||||||
let mut size_counter = ::ser::SizeChecker {
|
|
||||||
options: ::config::WithOtherLimit::new(
|
|
||||||
options,
|
|
||||||
CountSize {
|
|
||||||
total: 0,
|
|
||||||
other_limit: old_limiter,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
let result = value.serialize(&mut size_counter);
|
let result = value.serialize(&mut size_counter);
|
||||||
result.map(|_| size_counter.options.new_limit.total)
|
result.map(|_| size_counter.total)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn deserialize_from<R, T, O>(reader: R, options: O) -> Result<T>
|
pub(crate) fn deserialize_from<R, T, O>(reader: R, options: O) -> Result<T>
|
||||||
|
|
@ -111,7 +84,7 @@ where
|
||||||
T: serde::de::DeserializeSeed<'a>,
|
T: serde::de::DeserializeSeed<'a>,
|
||||||
O: Options,
|
O: Options,
|
||||||
{
|
{
|
||||||
let mut deserializer = ::de::Deserializer::<_, O>::new(reader, options);
|
let mut deserializer = ::de::Deserializer::<_, O>::with_bincode_read(reader, options);
|
||||||
seed.deserialize(&mut deserializer)
|
seed.deserialize(&mut deserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -121,7 +94,7 @@ where
|
||||||
T: serde::de::Deserialize<'a>,
|
T: serde::de::Deserialize<'a>,
|
||||||
O: Options,
|
O: Options,
|
||||||
{
|
{
|
||||||
let mut deserializer = ::de::Deserializer::<_, _>::new(reader, options);
|
let mut deserializer = ::de::Deserializer::<_, _>::with_bincode_read(reader, options);
|
||||||
serde::Deserialize::deserialize_in_place(&mut deserializer, place)
|
serde::Deserialize::deserialize_in_place(&mut deserializer, place)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -142,50 +115,3 @@ where
|
||||||
let options = ::config::WithOtherLimit::new(options, Infinite);
|
let options = ::config::WithOtherLimit::new(options, Infinite);
|
||||||
deserialize_from_custom_seed(seed, reader, options)
|
deserialize_from_custom_seed(seed, reader, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) trait SizeLimit: Clone {
|
|
||||||
/// 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<()>;
|
|
||||||
/// Returns the hard limit (if one exists)
|
|
||||||
fn limit(&self) -> Option<u64>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A SizeLimit that restricts serialized or deserialized messages from
|
|
||||||
/// exceeding a certain byte length.
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct Bounded(pub u64);
|
|
||||||
|
|
||||||
/// A SizeLimit without a limit!
|
|
||||||
/// Use this if you don't care about the size of encoded or decoded messages.
|
|
||||||
#[derive(Copy, Clone)]
|
|
||||||
pub struct Infinite;
|
|
||||||
|
|
||||||
impl SizeLimit for Bounded {
|
|
||||||
#[inline(always)]
|
|
||||||
fn add(&mut self, n: u64) -> Result<()> {
|
|
||||||
if self.0 >= n {
|
|
||||||
self.0 -= n;
|
|
||||||
Ok(())
|
|
||||||
} else {
|
|
||||||
Err(Box::new(ErrorKind::SizeLimit))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn limit(&self) -> Option<u64> {
|
|
||||||
Some(self.0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SizeLimit for Infinite {
|
|
||||||
#[inline(always)]
|
|
||||||
fn add(&mut self, _: u64) -> Result<()> {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn limit(&self) -> Option<u64> {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
78
src/lib.rs
78
src/lib.rs
|
|
@ -33,43 +33,20 @@ extern crate byteorder;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde;
|
extern crate serde;
|
||||||
|
|
||||||
mod config;
|
/// Configuration settings for bincode.
|
||||||
mod de;
|
pub mod config;
|
||||||
|
/// Deserialize bincode data to a Rust data structure.
|
||||||
|
pub mod de;
|
||||||
|
|
||||||
mod error;
|
mod error;
|
||||||
mod internal;
|
mod internal;
|
||||||
mod ser;
|
mod ser;
|
||||||
|
|
||||||
pub use config::Config;
|
pub use config::{Config, DefaultOptions, OptionsExt};
|
||||||
pub use de::read::{BincodeRead, IoReader, SliceReader};
|
pub use de::read::BincodeRead;
|
||||||
|
pub use de::Deserializer;
|
||||||
pub use error::{Error, ErrorKind, Result};
|
pub use error::{Error, ErrorKind, Result};
|
||||||
|
pub use ser::Serializer;
|
||||||
/// An object that implements this trait can be passed a
|
|
||||||
/// serde::Deserializer without knowing its concrete type.
|
|
||||||
///
|
|
||||||
/// This trait should be used only for `with_deserializer` functions.
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub trait DeserializerAcceptor<'a> {
|
|
||||||
/// The return type for the accept method
|
|
||||||
type Output;
|
|
||||||
/// Accept a serde::Deserializer and do whatever you want with it.
|
|
||||||
fn accept<T>(self, T) -> Self::Output
|
|
||||||
where
|
|
||||||
T: serde::Deserializer<'a, Error = Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An object that implements this trait can be passed a
|
|
||||||
/// serde::Serializer without knowing its concrete type.
|
|
||||||
///
|
|
||||||
/// This trait should be used only for `with_serializer` functions.
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub trait SerializerAcceptor {
|
|
||||||
/// The return type for the accept method
|
|
||||||
type Output;
|
|
||||||
/// Accept a serde::Serializer and do whatever you want with it.
|
|
||||||
fn accept<T>(self, T) -> Self::Output
|
|
||||||
where
|
|
||||||
T: serde::Serializer<Ok = (), Error = Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get a default configuration object.
|
/// Get a default configuration object.
|
||||||
///
|
///
|
||||||
|
|
@ -79,6 +56,7 @@ pub trait SerializerAcceptor {
|
||||||
/// |------------|------------|
|
/// |------------|------------|
|
||||||
/// | Unlimited | Little |
|
/// | Unlimited | Little |
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
#[deprecated(since = "1.3.0", note = "please use `DefaultOptions::new()` instead")]
|
||||||
pub fn config() -> Config {
|
pub fn config() -> Config {
|
||||||
Config::new()
|
Config::new()
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +70,7 @@ where
|
||||||
W: std::io::Write,
|
W: std::io::Write,
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
config().serialize_into(writer, value)
|
DefaultOptions::new().serialize_into(writer, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Serializes a serializable object into a `Vec` of bytes using the default configuration.
|
/// Serializes a serializable object into a `Vec` of bytes using the default configuration.
|
||||||
|
|
@ -100,7 +78,7 @@ pub fn serialize<T: ?Sized>(value: &T) -> Result<Vec<u8>>
|
||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
config().serialize(value)
|
DefaultOptions::new().serialize(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes an object directly from a `Read`er using the default configuration.
|
/// Deserializes an object directly from a `Read`er using the default configuration.
|
||||||
|
|
@ -111,7 +89,7 @@ where
|
||||||
R: std::io::Read,
|
R: std::io::Read,
|
||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
config().deserialize_from(reader)
|
DefaultOptions::new().deserialize_from(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
|
/// Deserializes an object from a custom `BincodeRead`er using the default configuration.
|
||||||
|
|
@ -124,7 +102,7 @@ where
|
||||||
R: de::read::BincodeRead<'a>,
|
R: de::read::BincodeRead<'a>,
|
||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
{
|
{
|
||||||
config().deserialize_from_custom(reader)
|
DefaultOptions::new().deserialize_from_custom(reader)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Only use this if you know what you're doing.
|
/// Only use this if you know what you're doing.
|
||||||
|
|
@ -136,7 +114,7 @@ where
|
||||||
T: serde::de::Deserialize<'a>,
|
T: serde::de::Deserialize<'a>,
|
||||||
R: BincodeRead<'a>,
|
R: BincodeRead<'a>,
|
||||||
{
|
{
|
||||||
config().deserialize_in_place(reader, place)
|
DefaultOptions::new().deserialize_in_place(reader, place)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deserializes a slice of bytes into an instance of `T` using the default configuration.
|
/// Deserializes a slice of bytes into an instance of `T` using the default configuration.
|
||||||
|
|
@ -144,7 +122,7 @@ pub fn deserialize<'a, T>(bytes: &'a [u8]) -> Result<T>
|
||||||
where
|
where
|
||||||
T: serde::de::Deserialize<'a>,
|
T: serde::de::Deserialize<'a>,
|
||||||
{
|
{
|
||||||
config().deserialize(bytes)
|
DefaultOptions::new().deserialize(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the size that an object would be if serialized using Bincode with the default configuration.
|
/// Returns the size that an object would be if serialized using Bincode with the default configuration.
|
||||||
|
|
@ -152,27 +130,5 @@ pub fn serialized_size<T: ?Sized>(value: &T) -> Result<u64>
|
||||||
where
|
where
|
||||||
T: serde::Serialize,
|
T: serde::Serialize,
|
||||||
{
|
{
|
||||||
config().serialized_size(value)
|
DefaultOptions::new().serialized_size(value)
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes the acceptor with a serde::Deserializer instance.
|
|
||||||
/// NOT A PART OF THE STABLE PUBLIC API
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn with_deserializer<'a, A, R>(reader: R, acceptor: A) -> A::Output
|
|
||||||
where
|
|
||||||
A: DeserializerAcceptor<'a>,
|
|
||||||
R: BincodeRead<'a>,
|
|
||||||
{
|
|
||||||
config().with_deserializer(reader, acceptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Executes the acceptor with a serde::Serializer instance.
|
|
||||||
/// NOT A PART OF THE STABLE PUBLIC API
|
|
||||||
#[doc(hidden)]
|
|
||||||
pub fn with_serializer<A, W>(writer: W, acceptor: A) -> A::Output
|
|
||||||
where
|
|
||||||
A: SerializerAcceptor,
|
|
||||||
W: std::io::Write,
|
|
||||||
{
|
|
||||||
config().with_serializer(writer, acceptor)
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,9 @@ use serde;
|
||||||
|
|
||||||
use byteorder::WriteBytesExt;
|
use byteorder::WriteBytesExt;
|
||||||
|
|
||||||
use super::internal::SizeLimit;
|
use super::config::SizeLimit;
|
||||||
use super::{Error, ErrorKind, Result};
|
use super::{Error, ErrorKind, Result};
|
||||||
use config::Options;
|
use config::{BincodeByteOrder, Options};
|
||||||
|
|
||||||
/// An Serializer that encodes values directly into a Writer.
|
/// An Serializer that encodes values directly into a Writer.
|
||||||
///
|
///
|
||||||
|
|
@ -16,7 +16,7 @@ use config::Options;
|
||||||
///
|
///
|
||||||
/// This struct should not be used often.
|
/// This struct should not be used often.
|
||||||
/// For most cases, prefer the `encode_into` function.
|
/// For most cases, prefer the `encode_into` function.
|
||||||
pub(crate) struct Serializer<W, O: Options> {
|
pub struct Serializer<W, O: Options> {
|
||||||
writer: W,
|
writer: W,
|
||||||
_options: O,
|
_options: O,
|
||||||
}
|
}
|
||||||
|
|
@ -61,15 +61,21 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_u16(self, v: u16) -> Result<()> {
|
fn serialize_u16(self, v: u16) -> Result<()> {
|
||||||
self.writer.write_u16::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_u16::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_u32(self, v: u32) -> Result<()> {
|
fn serialize_u32(self, v: u32) -> Result<()> {
|
||||||
self.writer.write_u32::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_u32::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_u64(self, v: u64) -> Result<()> {
|
fn serialize_u64(self, v: u64) -> Result<()> {
|
||||||
self.writer.write_u64::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_u64::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||||
|
|
@ -77,33 +83,43 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i16(self, v: i16) -> Result<()> {
|
fn serialize_i16(self, v: i16) -> Result<()> {
|
||||||
self.writer.write_i16::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_i16::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i32(self, v: i32) -> Result<()> {
|
fn serialize_i32(self, v: i32) -> Result<()> {
|
||||||
self.writer.write_i32::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_i32::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i64(self, v: i64) -> Result<()> {
|
fn serialize_i64(self, v: i64) -> Result<()> {
|
||||||
self.writer.write_i64::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_i64::<<O::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
serde_if_integer128! {
|
serde_if_integer128! {
|
||||||
fn serialize_u128(self, v: u128) -> Result<()> {
|
fn serialize_u128(self, v: u128) -> Result<()> {
|
||||||
self.writer.write_u128::<O::Endian>(v).map_err(Into::into)
|
self.writer.write_u128::<<O::Endian as BincodeByteOrder>::Endian>(v).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i128(self, v: i128) -> Result<()> {
|
fn serialize_i128(self, v: i128) -> Result<()> {
|
||||||
self.writer.write_i128::<O::Endian>(v).map_err(Into::into)
|
self.writer.write_i128::<<O::Endian as BincodeByteOrder>::Endian>(v).map_err(Into::into)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_f32(self, v: f32) -> Result<()> {
|
fn serialize_f32(self, v: f32) -> Result<()> {
|
||||||
self.writer.write_f32::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_f32::<<<O as Options>::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_f64(self, v: f64) -> Result<()> {
|
fn serialize_f64(self, v: f64) -> Result<()> {
|
||||||
self.writer.write_f64::<O::Endian>(v).map_err(Into::into)
|
self.writer
|
||||||
|
.write_f64::<<<O as Options>::Endian as BincodeByteOrder>::Endian>(v)
|
||||||
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<()> {
|
fn serialize_str(self, v: &str) -> Result<()> {
|
||||||
|
|
@ -221,11 +237,15 @@ impl<'a, W: Write, O: Options> serde::Serializer for &'a mut Serializer<W, O> {
|
||||||
|
|
||||||
pub(crate) struct SizeChecker<O: Options> {
|
pub(crate) struct SizeChecker<O: Options> {
|
||||||
pub options: O,
|
pub options: O,
|
||||||
|
pub total: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<O: Options> SizeChecker<O> {
|
impl<O: Options> SizeChecker<O> {
|
||||||
fn add_raw(&mut self, size: u64) -> Result<()> {
|
fn add_raw(&mut self, size: u64) -> Result<()> {
|
||||||
self.options.limit().add(size)
|
self.options.limit().add(size)?;
|
||||||
|
self.total += size;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_value<T>(&mut self, t: T) -> Result<()> {
|
fn add_value<T>(&mut self, t: T) -> Result<()> {
|
||||||
|
|
@ -418,7 +438,7 @@ impl<'a, O: Options> serde::Serializer for &'a mut SizeChecker<O> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct Compound<'a, W: 'a, O: Options + 'a> {
|
pub struct Compound<'a, W: 'a, O: Options + 'a> {
|
||||||
ser: &'a mut Serializer<W, O>,
|
ser: &'a mut Serializer<W, O>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
160
tests/test.rs
160
tests/test.rs
|
|
@ -13,8 +13,8 @@ use std::fmt::{self, Debug};
|
||||||
use std::result::Result as StdResult;
|
use std::result::Result as StdResult;
|
||||||
|
|
||||||
use bincode::{
|
use bincode::{
|
||||||
config, deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
|
deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
|
||||||
ErrorKind, Result,
|
DefaultOptions, ErrorKind, OptionsExt, Result,
|
||||||
};
|
};
|
||||||
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
|
||||||
|
|
||||||
|
|
@ -33,10 +33,16 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let encoded = config().big_endian().serialize(&element).unwrap();
|
let encoded = DefaultOptions::new()
|
||||||
let decoded = config().big_endian().deserialize(&encoded[..]).unwrap();
|
.with_big_endian()
|
||||||
let decoded_reader = config()
|
.serialize(&element)
|
||||||
.big_endian()
|
.unwrap();
|
||||||
|
let decoded = DefaultOptions::new()
|
||||||
|
.with_big_endian()
|
||||||
|
.deserialize(&encoded[..])
|
||||||
|
.unwrap();
|
||||||
|
let decoded_reader = DefaultOptions::new()
|
||||||
|
.with_big_endian()
|
||||||
.deserialize_from(&mut &encoded[..])
|
.deserialize_from(&mut &encoded[..])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
@ -259,11 +265,15 @@ fn deserializing_errors() {
|
||||||
#[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> = config().limit(3).deserialize_from(&mut &serialized[..]);
|
let deserialized: Result<u32> = DefaultOptions::new()
|
||||||
|
.with_limit(3)
|
||||||
|
.deserialize_from(&mut &serialized[..]);
|
||||||
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> = config().limit(4).deserialize_from(&mut &serialized[..]);
|
let deserialized: Result<u32> = DefaultOptions::new()
|
||||||
|
.with_limit(4)
|
||||||
|
.deserialize_from(&mut &serialized[..]);
|
||||||
assert!(deserialized.is_ok());
|
assert!(deserialized.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -271,8 +281,8 @@ fn too_big_deserialize() {
|
||||||
fn char_serialization() {
|
fn char_serialization() {
|
||||||
let chars = "Aa\0☺♪";
|
let chars = "Aa\0☺♪";
|
||||||
for c in chars.chars() {
|
for c in chars.chars() {
|
||||||
let encoded = config()
|
let encoded = DefaultOptions::new()
|
||||||
.limit(4)
|
.with_limit(4)
|
||||||
.serialize(&c)
|
.serialize(&c)
|
||||||
.expect("serializing char failed");
|
.expect("serializing char failed");
|
||||||
let decoded: char = deserialize(&encoded).expect("deserializing failed");
|
let decoded: char = deserialize(&encoded).expect("deserializing failed");
|
||||||
|
|
@ -283,18 +293,29 @@ fn char_serialization() {
|
||||||
#[test]
|
#[test]
|
||||||
fn too_big_char_deserialize() {
|
fn too_big_char_deserialize() {
|
||||||
let serialized = vec![0x41];
|
let serialized = vec![0x41];
|
||||||
let deserialized: Result<char> = config().limit(1).deserialize_from(&mut &serialized[..]);
|
let deserialized: Result<char> = DefaultOptions::new()
|
||||||
|
.with_limit(1)
|
||||||
|
.deserialize_from(&mut &serialized[..]);
|
||||||
assert!(deserialized.is_ok());
|
assert!(deserialized.is_ok());
|
||||||
assert_eq!(deserialized.unwrap(), 'A');
|
assert_eq!(deserialized.unwrap(), 'A');
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn too_big_serialize() {
|
fn too_big_serialize() {
|
||||||
assert!(config().limit(3).serialize(&0u32).is_err());
|
assert!(DefaultOptions::new()
|
||||||
assert!(config().limit(4).serialize(&0u32).is_ok());
|
.with_limit(3)
|
||||||
|
.serialize(&0u32)
|
||||||
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new().with_limit(4).serialize(&0u32).is_ok());
|
||||||
|
|
||||||
assert!(config().limit(8 + 4).serialize(&"abcde").is_err());
|
assert!(DefaultOptions::new()
|
||||||
assert!(config().limit(8 + 5).serialize(&"abcde").is_ok());
|
.with_limit(8 + 4)
|
||||||
|
.serialize(&"abcde")
|
||||||
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new()
|
||||||
|
.with_limit(8 + 5)
|
||||||
|
.serialize(&"abcde")
|
||||||
|
.is_ok());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
@ -314,28 +335,82 @@ fn test_serialized_size() {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serialized_size_bounded() {
|
fn test_serialized_size_bounded() {
|
||||||
// JUST RIGHT
|
// JUST RIGHT
|
||||||
assert!(config().limit(1).serialized_size(&0u8).unwrap() == 1);
|
|
||||||
assert!(config().limit(2).serialized_size(&0u16).unwrap() == 2);
|
|
||||||
assert!(config().limit(4).serialized_size(&0u32).unwrap() == 4);
|
|
||||||
assert!(config().limit(8).serialized_size(&0u64).unwrap() == 8);
|
|
||||||
assert!(config().limit(8).serialized_size(&"").unwrap() == 8);
|
|
||||||
assert!(config().limit(8 + 1).serialized_size(&"a").unwrap() == 8 + 1);
|
|
||||||
assert!(
|
assert!(
|
||||||
config()
|
DefaultOptions::new()
|
||||||
.limit(8 + 3 * 4)
|
.with_limit(1)
|
||||||
|
.serialized_size(&0u8)
|
||||||
|
.unwrap()
|
||||||
|
== 1
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
DefaultOptions::new()
|
||||||
|
.with_limit(2)
|
||||||
|
.serialized_size(&0u16)
|
||||||
|
.unwrap()
|
||||||
|
== 2
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
DefaultOptions::new()
|
||||||
|
.with_limit(4)
|
||||||
|
.serialized_size(&0u32)
|
||||||
|
.unwrap()
|
||||||
|
== 4
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
DefaultOptions::new()
|
||||||
|
.with_limit(8)
|
||||||
|
.serialized_size(&0u64)
|
||||||
|
.unwrap()
|
||||||
|
== 8
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
DefaultOptions::new()
|
||||||
|
.with_limit(8)
|
||||||
|
.serialized_size(&"")
|
||||||
|
.unwrap()
|
||||||
|
== 8
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
DefaultOptions::new()
|
||||||
|
.with_limit(8 + 1)
|
||||||
|
.serialized_size(&"a")
|
||||||
|
.unwrap()
|
||||||
|
== 8 + 1
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
DefaultOptions::new()
|
||||||
|
.with_limit(8 + 3 * 4)
|
||||||
.serialized_size(&vec![0u32, 1u32, 2u32])
|
.serialized_size(&vec![0u32, 1u32, 2u32])
|
||||||
.unwrap()
|
.unwrap()
|
||||||
== 8 + 3 * 4
|
== 8 + 3 * 4
|
||||||
);
|
);
|
||||||
// Below
|
// Below
|
||||||
assert!(config().limit(0).serialized_size(&0u8).is_err());
|
assert!(DefaultOptions::new()
|
||||||
assert!(config().limit(1).serialized_size(&0u16).is_err());
|
.with_limit(0)
|
||||||
assert!(config().limit(3).serialized_size(&0u32).is_err());
|
.serialized_size(&0u8)
|
||||||
assert!(config().limit(7).serialized_size(&0u64).is_err());
|
.is_err());
|
||||||
assert!(config().limit(7).serialized_size(&"").is_err());
|
assert!(DefaultOptions::new()
|
||||||
assert!(config().limit(8 + 0).serialized_size(&"a").is_err());
|
.with_limit(1)
|
||||||
assert!(config()
|
.serialized_size(&0u16)
|
||||||
.limit(8 + 3 * 4 - 1)
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new()
|
||||||
|
.with_limit(3)
|
||||||
|
.serialized_size(&0u32)
|
||||||
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new()
|
||||||
|
.with_limit(7)
|
||||||
|
.serialized_size(&0u64)
|
||||||
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new()
|
||||||
|
.with_limit(7)
|
||||||
|
.serialized_size(&"")
|
||||||
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new()
|
||||||
|
.with_limit(8 + 0)
|
||||||
|
.serialized_size(&"a")
|
||||||
|
.is_err());
|
||||||
|
assert!(DefaultOptions::new()
|
||||||
|
.with_limit(8 + 3 * 4 - 1)
|
||||||
.serialized_size(&vec![0u32, 1u32, 2u32])
|
.serialized_size(&vec![0u32, 1u32, 2u32])
|
||||||
.is_err());
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
@ -416,15 +491,15 @@ fn test_oom_protection() {
|
||||||
len: u64,
|
len: u64,
|
||||||
byte: u8,
|
byte: u8,
|
||||||
}
|
}
|
||||||
let x = config()
|
let x = DefaultOptions::new()
|
||||||
.limit(10)
|
.with_limit(10)
|
||||||
.serialize(&FakeVec {
|
.serialize(&FakeVec {
|
||||||
len: 0xffffffffffffffffu64,
|
len: 0xffffffffffffffffu64,
|
||||||
byte: 1,
|
byte: 1,
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let y: Result<Vec<u8>> = config()
|
let y: Result<Vec<u8>> = DefaultOptions::new()
|
||||||
.limit(10)
|
.with_limit(10)
|
||||||
.deserialize_from(&mut Cursor::new(&x[..]));
|
.deserialize_from(&mut Cursor::new(&x[..]));
|
||||||
assert!(y.is_err());
|
assert!(y.is_err());
|
||||||
}
|
}
|
||||||
|
|
@ -458,7 +533,10 @@ fn serde_bytes() {
|
||||||
fn endian_difference() {
|
fn endian_difference() {
|
||||||
let x = 10u64;
|
let x = 10u64;
|
||||||
let little = serialize(&x).unwrap();
|
let little = serialize(&x).unwrap();
|
||||||
let big = config().big_endian().serialize(&x).unwrap();
|
let big = DefaultOptions::new()
|
||||||
|
.with_big_endian()
|
||||||
|
.serialize(&x)
|
||||||
|
.unwrap();
|
||||||
assert_ne!(little, big);
|
assert_ne!(little, big);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -647,7 +725,7 @@ where
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_deserialize_seed() {
|
fn test_default_deserialize_seed() {
|
||||||
let config = config();
|
let config = DefaultOptions::new();
|
||||||
|
|
||||||
let data: Vec<_> = (10..100).collect();
|
let data: Vec<_> = (10..100).collect();
|
||||||
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
||||||
|
|
@ -665,8 +743,7 @@ fn test_default_deserialize_seed() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_big_endian_deserialize_seed() {
|
fn test_big_endian_deserialize_seed() {
|
||||||
let mut config = config();
|
let config = DefaultOptions::new().with_big_endian();
|
||||||
config.big_endian();
|
|
||||||
|
|
||||||
let data: Vec<_> = (10..100).collect();
|
let data: Vec<_> = (10..100).collect();
|
||||||
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
||||||
|
|
@ -684,7 +761,7 @@ fn test_big_endian_deserialize_seed() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_default_deserialize_from_seed() {
|
fn test_default_deserialize_from_seed() {
|
||||||
let config = config();
|
let config = DefaultOptions::new();
|
||||||
|
|
||||||
let data: Vec<_> = (10..100).collect();
|
let data: Vec<_> = (10..100).collect();
|
||||||
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
||||||
|
|
@ -702,8 +779,7 @@ fn test_default_deserialize_from_seed() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_big_endian_deserialize_from_seed() {
|
fn test_big_endian_deserialize_from_seed() {
|
||||||
let mut config = config();
|
let config = DefaultOptions::new().with_big_endian();
|
||||||
config.big_endian();
|
|
||||||
|
|
||||||
let data: Vec<_> = (10..100).collect();
|
let data: Vec<_> = (10..100).collect();
|
||||||
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
let bytes = config.serialize(&data).expect("Config::serialize failed");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue