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 
30 use de::read::BincodeRead;
31 use error::Result;
32 use serde;
33 use std::io::{Read, Write};
34 use std::marker::PhantomData;
35 
36 pub(crate) use self::endian::BincodeByteOrder;
37 pub(crate) use self::int::IntEncoding;
38 pub(crate) use self::internal::*;
39 pub(crate) use self::limit::SizeLimit;
40 pub(crate) use self::trailing::TrailingBytes;
41 
42 pub use self::endian::{BigEndian, LittleEndian, NativeEndian};
43 pub use self::int::{FixintEncoding, VarintEncoding};
44 pub use self::legacy::*;
45 pub use self::limit::{Bounded, Infinite};
46 pub use self::trailing::{AllowTrailing, RejectTrailing};
47 
48 mod endian;
49 mod int;
50 mod legacy;
51 mod limit;
52 mod 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)]
77 pub struct DefaultOptions(Infinite);
78 
79 impl 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            |
new() -> DefaultOptions87     pub fn new() -> DefaultOptions {
88         DefaultOptions(Infinite)
89     }
90 }
91 
92 impl Default for DefaultOptions {
default() -> Self93     fn default() -> Self {
94         Self::new()
95     }
96 }
97 
98 impl InternalOptions for DefaultOptions {
99     type Limit = Infinite;
100     type Endian = LittleEndian;
101     type IntEncoding = VarintEncoding;
102     type Trailing = RejectTrailing;
103 
104     #[inline(always)]
limit(&mut self) -> &mut Infinite105     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.
128 pub trait Options: InternalOptions + Sized {
129     /// Sets the byte limit to be unlimited.
130     /// This is the default.
with_no_limit(self) -> WithOtherLimit<Self, Infinite>131     fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
132         WithOtherLimit::new(self, Infinite)
133     }
134 
135     /// Sets the byte limit to `limit`.
with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded>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.
with_little_endian(self) -> WithOtherEndian<Self, LittleEndian>142     fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
143         WithOtherEndian::new(self)
144     }
145 
146     /// Sets the endianness to big-endian
with_big_endian(self) -> WithOtherEndian<Self, BigEndian>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
with_native_endian(self) -> WithOtherEndian<Self, NativeEndian>152     fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
153         WithOtherEndian::new(self)
154     }
155 
156     /// Sets the length encoding to varint
with_varint_encoding(self) -> WithOtherIntEncoding<Self, VarintEncoding>157     fn with_varint_encoding(self) -> WithOtherIntEncoding<Self, VarintEncoding> {
158         WithOtherIntEncoding::new(self)
159     }
160 
161     /// Sets the length encoding to be fixed
with_fixint_encoding(self) -> WithOtherIntEncoding<Self, FixintEncoding>162     fn with_fixint_encoding(self) -> WithOtherIntEncoding<Self, FixintEncoding> {
163         WithOtherIntEncoding::new(self)
164     }
165 
166     /// Sets the deserializer to reject trailing bytes
reject_trailing_bytes(self) -> WithOtherTrailing<Self, RejectTrailing>167     fn reject_trailing_bytes(self) -> WithOtherTrailing<Self, RejectTrailing> {
168         WithOtherTrailing::new(self)
169     }
170 
171     /// Sets the deserializer to allow trailing bytes
allow_trailing_bytes(self) -> WithOtherTrailing<Self, AllowTrailing>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)]
serialize<S: ?Sized + serde::Serialize>(self, t: &S) -> Result<Vec<u8>>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)]
serialized_size<T: ?Sized + serde::Serialize>(self, t: &T) -> Result<u64>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)]
serialize_into<W: Write, T: ?Sized + serde::Serialize>(self, w: W, t: &T) -> Result<()>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)]
deserialize<'a, T: serde::Deserialize<'a>>(self, bytes: &'a [u8]) -> Result<T>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)]
deserialize_in_place<'a, R, T>(self, reader: R, place: &mut T) -> Result<()> where R: BincodeRead<'a>, T: serde::de::Deserialize<'a>,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)]
deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>( self, seed: T, bytes: &'a [u8], ) -> Result<T::Value>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)]
deserialize_from<R: Read, T: serde::de::DeserializeOwned>(self, reader: R) -> Result<T>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)]
deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>( self, seed: T, reader: R, ) -> Result<T::Value>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)]
deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>( self, reader: R, ) -> Result<T>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)]
deserialize_from_custom_seed<'a, R: BincodeRead<'a>, T: serde::de::DeserializeSeed<'a>>( self, seed: T, reader: R, ) -> Result<T::Value>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 
272 impl<T: InternalOptions> Options for T {}
273 
274 /// A configuration struct with a user-specified byte limit
275 #[derive(Clone, Copy)]
276 pub 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)]
283 pub 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)]
290 pub 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)]
297 pub struct WithOtherTrailing<O: Options, T: TrailingBytes> {
298     options: O,
299     _trailing: PhantomData<T>,
300 }
301 
302 impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
303     #[inline(always)]
new(options: O, limit: L) -> WithOtherLimit<O, L>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 
312 impl<O: Options, E: BincodeByteOrder> WithOtherEndian<O, E> {
313     #[inline(always)]
new(options: O) -> WithOtherEndian<O, E>314     pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
315         WithOtherEndian {
316             options,
317             _endian: PhantomData,
318         }
319     }
320 }
321 
322 impl<O: Options, I: IntEncoding> WithOtherIntEncoding<O, I> {
323     #[inline(always)]
new(options: O) -> WithOtherIntEncoding<O, I>324     pub(crate) fn new(options: O) -> WithOtherIntEncoding<O, I> {
325         WithOtherIntEncoding {
326             options,
327             _length: PhantomData,
328         }
329     }
330 }
331 
332 impl<O: Options, T: TrailingBytes> WithOtherTrailing<O, T> {
333     #[inline(always)]
new(options: O) -> WithOtherTrailing<O, T>334     pub(crate) fn new(options: O) -> WithOtherTrailing<O, T> {
335         WithOtherTrailing {
336             options,
337             _trailing: PhantomData,
338         }
339     }
340 }
341 
342 impl<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)]
limit(&mut self) -> &mut O::Limit348     fn limit(&mut self) -> &mut O::Limit {
349         self.options.limit()
350     }
351 }
352 
353 impl<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;
limit(&mut self) -> &mut L358     fn limit(&mut self) -> &mut L {
359         &mut self.new_limit
360     }
361 }
362 
363 impl<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 
limit(&mut self) -> &mut O::Limit369     fn limit(&mut self) -> &mut O::Limit {
370         self.options.limit()
371     }
372 }
373 
374 impl<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 
limit(&mut self) -> &mut O::Limit380     fn limit(&mut self) -> &mut O::Limit {
381         self.options.limit()
382     }
383 }
384 
385 mod 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 
limit(&mut self) -> &mut Self::Limit394         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)]
limit(&mut self) -> &mut Self::Limit404         fn limit(&mut self) -> &mut Self::Limit {
405             (*self).limit()
406         }
407     }
408 }
409