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:
Lena Hellström 2020-04-16 15:23:07 -07:00 committed by GitHub
parent 8839b0600d
commit 2355e48a7b
7 changed files with 478 additions and 288 deletions

View File

@ -1,64 +1,43 @@
use super::internal::{Bounded, Infinite, SizeLimit};
use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
use byteorder;
use de::read::BincodeRead;
use error::Result;
use error::{ErrorKind, Result};
use serde;
use std::io::{Read, Write};
use std::marker::PhantomData;
use {DeserializerAcceptor, SerializerAcceptor};
pub(crate) use self::internal::*;
use self::EndianOption::*;
use self::LimitOption::*;
struct DefaultOptions(Infinite);
pub(crate) trait Options {
type Limit: SizeLimit + 'static;
type Endian: ByteOrder + 'static;
fn limit(&mut self) -> &mut Self::Limit;
}
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 {}
/// The default options for bincode serialization/deserialization.
/// Implements OptionsExt to allow building configuration object for non-default settings.
///
/// ### Defaults
/// By default bincode will use little-endian encoding for mult-byte integers, and will not
/// limit the number of serialized/deserialized bytes.
#[derive(Copy, Clone)]
pub struct DefaultOptions(Infinite);
impl DefaultOptions {
fn new() -> DefaultOptions {
/// Get a default configuration object.
///
/// ### Default Configuration:
///
/// | Byte limit | Endianness |
/// |------------|------------|
/// | Unlimited | Little |
pub fn new() -> DefaultOptions {
DefaultOptions(Infinite)
}
}
impl Default for DefaultOptions {
fn default() -> Self {
Self::new()
}
}
impl Options for DefaultOptions {
type Limit = Infinite;
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)]
enum LimitOption {
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
/// serialization that goes over the limit.
#[derive(Clone, Debug)]
#[deprecated(
since = "1.3.0",
note = "please use the `DefaultOptions`/`OptionsExt` system instead"
)]
pub struct Config {
limit: LimitOption,
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,
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,
_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)]
pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
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 Endian = E;
@ -333,32 +525,39 @@ impl Config {
) -> Result<T::Value> {
config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
}
}
/// 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>(&self, reader: R, acceptor: A) -> A::Output
where
A: DeserializerAcceptor<'a>,
R: BincodeRead<'a>,
{
config_map!(self, opts => {
let mut deserializer = ::de::Deserializer::new(reader, opts);
acceptor.accept(&mut deserializer)
})
mod internal {
use super::*;
use byteorder::ByteOrder;
pub trait Options {
type Limit: SizeLimit + 'static;
type Endian: BincodeByteOrder + 'static;
fn limit(&mut self) -> &mut Self::Limit;
}
/// Executes the acceptor with a serde::Serializer instance.
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub fn with_serializer<A, W>(&self, writer: W, acceptor: A) -> A::Output
where
A: SerializerAcceptor,
W: Write,
{
config_map!(self, opts => {
let mut serializer = ::ser::Serializer::new(writer, opts);
acceptor.accept(&mut serializer)
})
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()
}
}
/// 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;
}
}

View File

@ -1,14 +1,15 @@
use config::Options;
use config::{BincodeByteOrder, Options};
use std::io::Read;
use self::read::BincodeRead;
use self::read::{BincodeRead, IoReader, SliceReader};
use byteorder::ReadBytesExt;
use internal::SizeLimit;
use config::SizeLimit;
use serde;
use serde::de::Error as DeError;
use serde::de::IntoDeserializer;
use {Error, ErrorKind, Result};
/// Specialized ways to read data into bincode.
pub mod read;
/// A Deserializer that reads bytes from a buffer.
@ -24,14 +25,30 @@ pub mod read;
/// serde::Deserialize::deserialize(&mut deserializer);
/// let bytes_read = d.bytes_read();
/// ```
pub(crate) struct Deserializer<R, O: Options> {
pub struct Deserializer<R, O: Options> {
reader: R,
options: O,
}
impl<'de, R: BincodeRead<'de>, O: Options> Deserializer<R, O> {
/// Creates a new Deserializer with a given `Read`er and a size_limit.
pub(crate) fn new(r: R, options: O) -> Deserializer<R, O> {
/// Creates a new Deserializer with a given `Read`er and options.
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 }
}
@ -63,7 +80,7 @@ macro_rules! impl_nums {
where V: serde::de::Visitor<'de>,
{
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)
}
}

View File

@ -27,15 +27,11 @@ pub trait BincodeRead<'storage>: io::Read {
}
/// A BincodeRead implementation for byte slices
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
pub struct SliceReader<'storage> {
slice: &'storage [u8],
}
/// A BincodeRead implementation for io::Readers
/// NOT A PART OF THE STABLE PUBLIC API
#[doc(hidden)]
/// A BincodeRead implementation for `io::Read`ers
pub struct IoReader<R> {
reader: R,
temp_buffer: Vec<u8>,
@ -43,7 +39,7 @@ pub struct IoReader<R> {
impl<'storage> SliceReader<'storage> {
/// Constructs a slice reader
pub fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
pub(crate) fn new(bytes: &'storage [u8]) -> SliceReader<'storage> {
SliceReader { slice: bytes }
}
@ -60,7 +56,7 @@ impl<'storage> SliceReader<'storage> {
impl<R> IoReader<R> {
/// Constructs an IoReadReader
pub fn new(r: R) -> IoReader<R> {
pub(crate) fn new(r: R) -> IoReader<R> {
IoReader {
reader: r,
temp_buffer: vec![],

View File

@ -2,15 +2,9 @@ use serde;
use std::io::{Read, Write};
use std::marker::PhantomData;
use config::{Options, OptionsExt};
use config::{Infinite, Options, OptionsExt, SizeLimit};
use de::read::BincodeRead;
use {ErrorKind, Result};
#[derive(Clone)]
struct CountSize<L: SizeLimit> {
total: u64,
other_limit: L,
}
use Result;
pub(crate) fn serialize_into<W, T: ?Sized, O>(writer: W, value: &T, mut options: O) -> Result<()>
where
@ -42,35 +36,14 @@ where
Ok(writer)
}
impl<L: SizeLimit> SizeLimit for CountSize<L> {
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>
pub(crate) fn serialized_size<T: ?Sized, O: Options>(value: &T, options: O) -> Result<u64>
where
T: serde::Serialize,
{
let old_limiter = options.limit().clone();
let mut size_counter = ::ser::SizeChecker {
options: ::config::WithOtherLimit::new(
options,
CountSize {
total: 0,
other_limit: old_limiter,
},
),
};
let mut size_counter = ::ser::SizeChecker { options, total: 0 };
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>
@ -111,7 +84,7 @@ where
T: serde::de::DeserializeSeed<'a>,
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)
}
@ -121,7 +94,7 @@ where
T: serde::de::Deserialize<'a>,
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)
}
@ -142,50 +115,3 @@ where
let options = ::config::WithOtherLimit::new(options, Infinite);
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
}
}

View File

@ -33,43 +33,20 @@ extern crate byteorder;
#[macro_use]
extern crate serde;
mod config;
mod de;
/// Configuration settings for bincode.
pub mod config;
/// Deserialize bincode data to a Rust data structure.
pub mod de;
mod error;
mod internal;
mod ser;
pub use config::Config;
pub use de::read::{BincodeRead, IoReader, SliceReader};
pub use config::{Config, DefaultOptions, OptionsExt};
pub use de::read::BincodeRead;
pub use de::Deserializer;
pub use error::{Error, ErrorKind, Result};
/// 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>;
}
pub use ser::Serializer;
/// Get a default configuration object.
///
@ -79,6 +56,7 @@ pub trait SerializerAcceptor {
/// |------------|------------|
/// | Unlimited | Little |
#[inline(always)]
#[deprecated(since = "1.3.0", note = "please use `DefaultOptions::new()` instead")]
pub fn config() -> Config {
Config::new()
}
@ -92,7 +70,7 @@ where
W: std::io::Write,
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.
@ -100,7 +78,7 @@ pub fn serialize<T: ?Sized>(value: &T) -> Result<Vec<u8>>
where
T: serde::Serialize,
{
config().serialize(value)
DefaultOptions::new().serialize(value)
}
/// Deserializes an object directly from a `Read`er using the default configuration.
@ -111,7 +89,7 @@ where
R: std::io::Read,
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.
@ -124,7 +102,7 @@ where
R: de::read::BincodeRead<'a>,
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.
@ -136,7 +114,7 @@ where
T: serde::de::Deserialize<'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.
@ -144,7 +122,7 @@ pub fn deserialize<'a, T>(bytes: &'a [u8]) -> Result<T>
where
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.
@ -152,27 +130,5 @@ pub fn serialized_size<T: ?Sized>(value: &T) -> Result<u64>
where
T: serde::Serialize,
{
config().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)
DefaultOptions::new().serialized_size(value)
}

View File

@ -5,9 +5,9 @@ use serde;
use byteorder::WriteBytesExt;
use super::internal::SizeLimit;
use super::config::SizeLimit;
use super::{Error, ErrorKind, Result};
use config::Options;
use config::{BincodeByteOrder, Options};
/// An Serializer that encodes values directly into a Writer.
///
@ -16,7 +16,7 @@ use config::Options;
///
/// This struct should not be used often.
/// For most cases, prefer the `encode_into` function.
pub(crate) struct Serializer<W, O: Options> {
pub struct Serializer<W, O: Options> {
writer: W,
_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<()> {
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<()> {
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<()> {
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<()> {
@ -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<()> {
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<()> {
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<()> {
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! {
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<()> {
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<()> {
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<()> {
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<()> {
@ -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 options: O,
pub total: u64,
}
impl<O: Options> SizeChecker<O> {
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<()> {
@ -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>,
}

View File

@ -13,8 +13,8 @@ use std::fmt::{self, Debug};
use std::result::Result as StdResult;
use bincode::{
config, deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
ErrorKind, Result,
deserialize, deserialize_from, deserialize_in_place, serialize, serialized_size,
DefaultOptions, ErrorKind, OptionsExt, Result,
};
use serde::de::{Deserialize, DeserializeSeed, Deserializer, SeqAccess, Visitor};
@ -33,10 +33,16 @@ where
}
{
let encoded = config().big_endian().serialize(&element).unwrap();
let decoded = config().big_endian().deserialize(&encoded[..]).unwrap();
let decoded_reader = config()
.big_endian()
let encoded = DefaultOptions::new()
.with_big_endian()
.serialize(&element)
.unwrap();
let decoded = DefaultOptions::new()
.with_big_endian()
.deserialize(&encoded[..])
.unwrap();
let decoded_reader = DefaultOptions::new()
.with_big_endian()
.deserialize_from(&mut &encoded[..])
.unwrap();
@ -259,11 +265,15 @@ fn deserializing_errors() {
#[test]
fn too_big_deserialize() {
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());
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());
}
@ -271,8 +281,8 @@ fn too_big_deserialize() {
fn char_serialization() {
let chars = "Aa\0☺♪";
for c in chars.chars() {
let encoded = config()
.limit(4)
let encoded = DefaultOptions::new()
.with_limit(4)
.serialize(&c)
.expect("serializing char failed");
let decoded: char = deserialize(&encoded).expect("deserializing failed");
@ -283,18 +293,29 @@ fn char_serialization() {
#[test]
fn too_big_char_deserialize() {
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_eq!(deserialized.unwrap(), 'A');
}
#[test]
fn too_big_serialize() {
assert!(config().limit(3).serialize(&0u32).is_err());
assert!(config().limit(4).serialize(&0u32).is_ok());
assert!(DefaultOptions::new()
.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!(config().limit(8 + 5).serialize(&"abcde").is_ok());
assert!(DefaultOptions::new()
.with_limit(8 + 4)
.serialize(&"abcde")
.is_err());
assert!(DefaultOptions::new()
.with_limit(8 + 5)
.serialize(&"abcde")
.is_ok());
}
#[test]
@ -314,28 +335,82 @@ fn test_serialized_size() {
#[test]
fn test_serialized_size_bounded() {
// 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!(
config()
.limit(8 + 3 * 4)
DefaultOptions::new()
.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])
.unwrap()
== 8 + 3 * 4
);
// Below
assert!(config().limit(0).serialized_size(&0u8).is_err());
assert!(config().limit(1).serialized_size(&0u16).is_err());
assert!(config().limit(3).serialized_size(&0u32).is_err());
assert!(config().limit(7).serialized_size(&0u64).is_err());
assert!(config().limit(7).serialized_size(&"").is_err());
assert!(config().limit(8 + 0).serialized_size(&"a").is_err());
assert!(config()
.limit(8 + 3 * 4 - 1)
assert!(DefaultOptions::new()
.with_limit(0)
.serialized_size(&0u8)
.is_err());
assert!(DefaultOptions::new()
.with_limit(1)
.serialized_size(&0u16)
.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])
.is_err());
}
@ -416,15 +491,15 @@ fn test_oom_protection() {
len: u64,
byte: u8,
}
let x = config()
.limit(10)
let x = DefaultOptions::new()
.with_limit(10)
.serialize(&FakeVec {
len: 0xffffffffffffffffu64,
byte: 1,
})
.unwrap();
let y: Result<Vec<u8>> = config()
.limit(10)
let y: Result<Vec<u8>> = DefaultOptions::new()
.with_limit(10)
.deserialize_from(&mut Cursor::new(&x[..]));
assert!(y.is_err());
}
@ -458,7 +533,10 @@ fn serde_bytes() {
fn endian_difference() {
let x = 10u64;
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);
}
@ -647,7 +725,7 @@ where
#[test]
fn test_default_deserialize_seed() {
let config = config();
let config = DefaultOptions::new();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
@ -665,8 +743,7 @@ fn test_default_deserialize_seed() {
#[test]
fn test_big_endian_deserialize_seed() {
let mut config = config();
config.big_endian();
let config = DefaultOptions::new().with_big_endian();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
@ -684,7 +761,7 @@ fn test_big_endian_deserialize_seed() {
#[test]
fn test_default_deserialize_from_seed() {
let config = config();
let config = DefaultOptions::new();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");
@ -702,8 +779,7 @@ fn test_default_deserialize_from_seed() {
#[test]
fn test_big_endian_deserialize_from_seed() {
let mut config = config();
config.big_endian();
let config = DefaultOptions::new().with_big_endian();
let data: Vec<_> = (10..100).collect();
let bytes = config.serialize(&data).expect("Config::serialize failed");