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}
409