bincode/config/
mod.rs

1//! `bincode` uses a Builder-pattern to configure the Serializers and Deserializers in this
2//! crate. This means that if you need to customize the behavior of `bincode`, you should create an
3//! instance of the `DefaultOptions` struct:
4//!
5//! ```rust
6//! use bincode::Options;
7//! let my_options = bincode::DefaultOptions::new();
8//! ```
9//!
10//! # Options Struct vs bincode functions
11//!
12//! Due to historical reasons, the default options used by the `serialize()` and `deserialize()`
13//! family of functions are different than the default options created by the `DefaultOptions` struct:
14//!
15//! |          | Byte limit | Endianness | Int Encoding | Trailing Behavior |
16//! |----------|------------|------------|--------------|-------------------|
17//! | struct   | Unlimited  | Little     | Varint       | Reject            |
18//! | function | Unlimited  | Little     | Fixint       | Allow             |
19//!
20//! This means that if you want to use the `Serialize` / `Deserialize` structs with the same
21//! settings as the functions, you should adjust the `DefaultOptions` struct like so:
22//!
23//! ```rust
24//! use bincode::Options;
25//! let my_options = bincode::DefaultOptions::new()
26//!     .with_fixint_encoding()
27//!     .allow_trailing_bytes();
28//! ```
29
30use de::read::BincodeRead;
31use error::Result;
32use serde;
33use std::io::{Read, Write};
34use std::marker::PhantomData;
35
36pub(crate) use self::endian::BincodeByteOrder;
37pub(crate) use self::int::IntEncoding;
38pub(crate) use self::internal::*;
39pub(crate) use self::limit::SizeLimit;
40pub(crate) use self::trailing::TrailingBytes;
41
42pub use self::endian::{BigEndian, LittleEndian, NativeEndian};
43pub use self::int::{FixintEncoding, VarintEncoding};
44pub use self::legacy::*;
45pub use self::limit::{Bounded, Infinite};
46pub use self::trailing::{AllowTrailing, RejectTrailing};
47
48mod endian;
49mod int;
50mod legacy;
51mod limit;
52mod trailing;
53
54/// The default options for bincode serialization/deserialization.
55///
56/// ### Defaults
57/// By default bincode will use little-endian encoding for multi-byte integers, and will not
58/// limit the number of serialized/deserialized bytes.
59///
60/// ### Configuring `DefaultOptions`
61///
62/// `DefaultOptions` implements the [Options] trait, which means it exposes functions to change the behavior of bincode.
63///
64/// For example, if you wanted to limit the bincode deserializer to 1 kilobyte of user input:
65///
66/// ```rust
67/// use bincode::Options;
68/// let my_options = bincode::DefaultOptions::new().with_limit(1024);
69/// ```
70///
71/// ### DefaultOptions struct vs. functions
72///
73/// The default configuration used by this struct is not the same as that used by the bincode
74/// helper functions in the root of this crate. See the
75/// [config](index.html#options-struct-vs-bincode-functions) module for more details
76#[derive(Copy, Clone)]
77pub struct DefaultOptions(Infinite);
78
79impl DefaultOptions {
80    /// Get a default configuration object.
81    ///
82    /// ### Default Configuration:
83    ///
84    /// | Byte limit | Endianness | Int Encoding | Trailing Behavior |
85    /// |------------|------------|--------------|-------------------|
86    /// | Unlimited  | Little     | Varint       | Reject            |
87    pub fn new() -> DefaultOptions {
88        DefaultOptions(Infinite)
89    }
90}
91
92impl Default for DefaultOptions {
93    fn default() -> Self {
94        Self::new()
95    }
96}
97
98impl InternalOptions for DefaultOptions {
99    type Limit = Infinite;
100    type Endian = LittleEndian;
101    type IntEncoding = VarintEncoding;
102    type Trailing = RejectTrailing;
103
104    #[inline(always)]
105    fn limit(&mut self) -> &mut Infinite {
106        &mut self.0
107    }
108}
109
110/// A configuration builder trait whose options Bincode will use
111/// while serializing and deserializing.
112///
113/// ### Options
114/// Endianness: The endianness with which multi-byte integers will be read/written.  *default: little endian*
115///
116/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
117///
118/// Int Encoding: The encoding used for numbers, enum discriminants, and lengths. *default: varint*
119///
120/// Trailing Behavior: The behavior when there are trailing bytes left over in a slice after deserialization. *default: reject*
121///
122/// ### Byte Limit Details
123/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
124/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
125///
126/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
127/// serialization that goes over the limit.
128pub trait Options: InternalOptions + Sized {
129    /// Sets the byte limit to be unlimited.
130    /// This is the default.
131    fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
132        WithOtherLimit::new(self, Infinite)
133    }
134
135    /// Sets the byte limit to `limit`.
136    fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
137        WithOtherLimit::new(self, Bounded(limit))
138    }
139
140    /// Sets the endianness to little-endian
141    /// This is the default.
142    fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
143        WithOtherEndian::new(self)
144    }
145
146    /// Sets the endianness to big-endian
147    fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
148        WithOtherEndian::new(self)
149    }
150
151    /// Sets the endianness to the the machine-native endianness
152    fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
153        WithOtherEndian::new(self)
154    }
155
156    /// Sets the length encoding to varint
157    fn with_varint_encoding(self) -> WithOtherIntEncoding<Self, VarintEncoding> {
158        WithOtherIntEncoding::new(self)
159    }
160
161    /// Sets the length encoding to be fixed
162    fn with_fixint_encoding(self) -> WithOtherIntEncoding<Self, FixintEncoding> {
163        WithOtherIntEncoding::new(self)
164    }
165
166    /// Sets the deserializer to reject trailing bytes
167    fn reject_trailing_bytes(self) -> WithOtherTrailing<Self, RejectTrailing> {
168        WithOtherTrailing::new(self)
169    }
170
171    /// Sets the deserializer to allow trailing bytes
172    fn allow_trailing_bytes(self) -> WithOtherTrailing<Self, AllowTrailing> {
173        WithOtherTrailing::new(self)
174    }
175
176    /// Serializes a serializable object into a `Vec` of bytes using this configuration
177    #[inline(always)]
178    fn serialize<S: ?Sized + serde::Serialize>(self, t: &S) -> Result<Vec<u8>> {
179        ::internal::serialize(t, self)
180    }
181
182    /// Returns the size that an object would be if serialized using Bincode with this configuration
183    #[inline(always)]
184    fn serialized_size<T: ?Sized + serde::Serialize>(self, t: &T) -> Result<u64> {
185        ::internal::serialized_size(t, self)
186    }
187
188    /// Serializes an object directly into a `Writer` using this configuration
189    ///
190    /// If the serialization would take more bytes than allowed by the size limit, an error
191    /// is returned and *no bytes* will be written into the `Writer`
192    #[inline(always)]
193    fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(self, w: W, t: &T) -> Result<()> {
194        ::internal::serialize_into(w, t, self)
195    }
196
197    /// Deserializes a slice of bytes into an instance of `T` using this configuration
198    #[inline(always)]
199    fn deserialize<'a, T: serde::Deserialize<'a>>(self, bytes: &'a [u8]) -> Result<T> {
200        ::internal::deserialize(bytes, self)
201    }
202
203    /// TODO: document
204    #[doc(hidden)]
205    #[inline(always)]
206    fn deserialize_in_place<'a, R, T>(self, reader: R, place: &mut T) -> Result<()>
207    where
208        R: BincodeRead<'a>,
209        T: serde::de::Deserialize<'a>,
210    {
211        ::internal::deserialize_in_place(reader, self, place)
212    }
213
214    /// Deserializes a slice of bytes with state `seed` using this configuration.
215    #[inline(always)]
216    fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
217        self,
218        seed: T,
219        bytes: &'a [u8],
220    ) -> Result<T::Value> {
221        ::internal::deserialize_seed(seed, bytes, self)
222    }
223
224    /// Deserializes an object directly from a `Read`er using this configuration
225    ///
226    /// If this returns an `Error`, `reader` may be in an invalid state.
227    #[inline(always)]
228    fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(self, reader: R) -> Result<T> {
229        ::internal::deserialize_from(reader, self)
230    }
231
232    /// Deserializes an object directly from a `Read`er with state `seed` using this configuration
233    ///
234    /// If this returns an `Error`, `reader` may be in an invalid state.
235    #[inline(always)]
236    fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
237        self,
238        seed: T,
239        reader: R,
240    ) -> Result<T::Value> {
241        ::internal::deserialize_from_seed(seed, reader, self)
242    }
243
244    /// Deserializes an object from a custom `BincodeRead`er using the default configuration.
245    /// It is highly recommended to use `deserialize_from` unless you need to implement
246    /// `BincodeRead` for performance reasons.
247    ///
248    /// If this returns an `Error`, `reader` may be in an invalid state.
249    #[inline(always)]
250    fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
251        self,
252        reader: R,
253    ) -> Result<T> {
254        ::internal::deserialize_from_custom(reader, self)
255    }
256
257    /// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
258    /// configuration. It is highly recommended to use `deserialize_from` unless you need to
259    /// implement `BincodeRead` for performance reasons.
260    ///
261    /// If this returns an `Error`, `reader` may be in an invalid state.
262    #[inline(always)]
263    fn deserialize_from_custom_seed<'a, R: BincodeRead<'a>, T: serde::de::DeserializeSeed<'a>>(
264        self,
265        seed: T,
266        reader: R,
267    ) -> Result<T::Value> {
268        ::internal::deserialize_from_custom_seed(seed, reader, self)
269    }
270}
271
272impl<T: InternalOptions> Options for T {}
273
274/// A configuration struct with a user-specified byte limit
275#[derive(Clone, Copy)]
276pub struct WithOtherLimit<O: Options, L: SizeLimit> {
277    _options: O,
278    pub(crate) new_limit: L,
279}
280
281/// A configuration struct with a user-specified endian order
282#[derive(Clone, Copy)]
283pub struct WithOtherEndian<O: Options, E: BincodeByteOrder> {
284    options: O,
285    _endian: PhantomData<E>,
286}
287
288/// A configuration struct with a user-specified length encoding
289#[derive(Clone, Copy)]
290pub struct WithOtherIntEncoding<O: Options, I: IntEncoding> {
291    options: O,
292    _length: PhantomData<I>,
293}
294
295/// A configuration struct with a user-specified trailing bytes behavior.
296#[derive(Clone, Copy)]
297pub struct WithOtherTrailing<O: Options, T: TrailingBytes> {
298    options: O,
299    _trailing: PhantomData<T>,
300}
301
302impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
303    #[inline(always)]
304    pub(crate) fn new(options: O, limit: L) -> WithOtherLimit<O, L> {
305        WithOtherLimit {
306            _options: options,
307            new_limit: limit,
308        }
309    }
310}
311
312impl<O: Options, E: BincodeByteOrder> WithOtherEndian<O, E> {
313    #[inline(always)]
314    pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
315        WithOtherEndian {
316            options,
317            _endian: PhantomData,
318        }
319    }
320}
321
322impl<O: Options, I: IntEncoding> WithOtherIntEncoding<O, I> {
323    #[inline(always)]
324    pub(crate) fn new(options: O) -> WithOtherIntEncoding<O, I> {
325        WithOtherIntEncoding {
326            options,
327            _length: PhantomData,
328        }
329    }
330}
331
332impl<O: Options, T: TrailingBytes> WithOtherTrailing<O, T> {
333    #[inline(always)]
334    pub(crate) fn new(options: O) -> WithOtherTrailing<O, T> {
335        WithOtherTrailing {
336            options,
337            _trailing: PhantomData,
338        }
339    }
340}
341
342impl<O: Options, E: BincodeByteOrder + 'static> InternalOptions for WithOtherEndian<O, E> {
343    type Limit = O::Limit;
344    type Endian = E;
345    type IntEncoding = O::IntEncoding;
346    type Trailing = O::Trailing;
347    #[inline(always)]
348    fn limit(&mut self) -> &mut O::Limit {
349        self.options.limit()
350    }
351}
352
353impl<O: Options, L: SizeLimit + 'static> InternalOptions for WithOtherLimit<O, L> {
354    type Limit = L;
355    type Endian = O::Endian;
356    type IntEncoding = O::IntEncoding;
357    type Trailing = O::Trailing;
358    fn limit(&mut self) -> &mut L {
359        &mut self.new_limit
360    }
361}
362
363impl<O: Options, I: IntEncoding + 'static> InternalOptions for WithOtherIntEncoding<O, I> {
364    type Limit = O::Limit;
365    type Endian = O::Endian;
366    type IntEncoding = I;
367    type Trailing = O::Trailing;
368
369    fn limit(&mut self) -> &mut O::Limit {
370        self.options.limit()
371    }
372}
373
374impl<O: Options, T: TrailingBytes + 'static> InternalOptions for WithOtherTrailing<O, T> {
375    type Limit = O::Limit;
376    type Endian = O::Endian;
377    type IntEncoding = O::IntEncoding;
378    type Trailing = T;
379
380    fn limit(&mut self) -> &mut O::Limit {
381        self.options.limit()
382    }
383}
384
385mod internal {
386    use super::*;
387
388    pub trait InternalOptions {
389        type Limit: SizeLimit + 'static;
390        type Endian: BincodeByteOrder + 'static;
391        type IntEncoding: IntEncoding + 'static;
392        type Trailing: TrailingBytes + 'static;
393
394        fn limit(&mut self) -> &mut Self::Limit;
395    }
396
397    impl<'a, O: InternalOptions> InternalOptions for &'a mut O {
398        type Limit = O::Limit;
399        type Endian = O::Endian;
400        type IntEncoding = O::IntEncoding;
401        type Trailing = O::Trailing;
402
403        #[inline(always)]
404        fn limit(&mut self) -> &mut Self::Limit {
405            (*self).limit()
406        }
407    }
408}