bincode_thin/
config.rs

1use super::internal::{Bounded, Infinite, SizeLimit};
2use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian};
3use de::read::BincodeRead;
4use error::Result;
5use serde;
6use std::io::{Read, Write};
7use std::marker::PhantomData;
8use {DeserializerAcceptor, SerializerAcceptor};
9
10use self::EndianOption::*;
11use self::LimitOption::*;
12
13struct DefaultOptions(Infinite);
14
15pub(crate) trait Options {
16    type Limit: SizeLimit + 'static;
17    type Endian: ByteOrder + 'static;
18
19    fn limit(&mut self) -> &mut Self::Limit;
20}
21
22pub(crate) trait OptionsExt: Options + Sized {
23    fn with_no_limit(self) -> WithOtherLimit<Self, Infinite> {
24        WithOtherLimit::new(self, Infinite)
25    }
26
27    fn with_limit(self, limit: u64) -> WithOtherLimit<Self, Bounded> {
28        WithOtherLimit::new(self, Bounded(limit))
29    }
30
31    fn with_little_endian(self) -> WithOtherEndian<Self, LittleEndian> {
32        WithOtherEndian::new(self)
33    }
34
35    fn with_big_endian(self) -> WithOtherEndian<Self, BigEndian> {
36        WithOtherEndian::new(self)
37    }
38
39    fn with_native_endian(self) -> WithOtherEndian<Self, NativeEndian> {
40        WithOtherEndian::new(self)
41    }
42}
43
44impl<'a, O: Options> Options for &'a mut O {
45    type Limit = O::Limit;
46    type Endian = O::Endian;
47
48    #[inline(always)]
49    fn limit(&mut self) -> &mut Self::Limit {
50        (*self).limit()
51    }
52}
53
54impl<T: Options> OptionsExt for T {}
55
56impl DefaultOptions {
57    fn new() -> DefaultOptions {
58        DefaultOptions(Infinite)
59    }
60}
61
62impl Options for DefaultOptions {
63    type Limit = Infinite;
64    type Endian = LittleEndian;
65
66    #[inline(always)]
67    fn limit(&mut self) -> &mut Infinite {
68        &mut self.0
69    }
70}
71
72#[derive(Clone, Copy)]
73enum LimitOption {
74    Unlimited,
75    Limited(u64),
76}
77
78#[derive(Clone, Copy)]
79enum EndianOption {
80    Big,
81    Little,
82    Native,
83}
84
85/// A configuration builder whose options Bincode will use
86/// while serializing and deserializing.
87///
88/// ### Options
89/// Endianness: The endianness with which multi-byte integers will be read/written.  *default: little endian*
90/// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
91///
92/// ### Byte Limit Details
93/// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
94/// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
95///
96/// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
97/// serialization that goes over the limit.
98pub struct Config {
99    limit: LimitOption,
100    endian: EndianOption,
101}
102
103pub(crate) struct WithOtherLimit<O: Options, L: SizeLimit> {
104    _options: O,
105    pub(crate) new_limit: L,
106}
107
108pub(crate) struct WithOtherEndian<O: Options, E: ByteOrder> {
109    options: O,
110    _endian: PhantomData<E>,
111}
112
113impl<O: Options, L: SizeLimit> WithOtherLimit<O, L> {
114    #[inline(always)]
115    pub(crate) fn new(options: O, limit: L) -> WithOtherLimit<O, L> {
116        WithOtherLimit {
117            _options: options,
118            new_limit: limit,
119        }
120    }
121}
122
123impl<O: Options, E: ByteOrder> WithOtherEndian<O, E> {
124    #[inline(always)]
125    pub(crate) fn new(options: O) -> WithOtherEndian<O, E> {
126        WithOtherEndian {
127            options: options,
128            _endian: PhantomData,
129        }
130    }
131}
132
133impl<O: Options, E: ByteOrder + 'static> Options for WithOtherEndian<O, E> {
134    type Limit = O::Limit;
135    type Endian = E;
136
137    #[inline(always)]
138    fn limit(&mut self) -> &mut O::Limit {
139        self.options.limit()
140    }
141}
142
143impl<O: Options, L: SizeLimit + 'static> Options for WithOtherLimit<O, L> {
144    type Limit = L;
145    type Endian = O::Endian;
146
147    fn limit(&mut self) -> &mut L {
148        &mut self.new_limit
149    }
150}
151
152macro_rules! config_map {
153    ($self:expr, $opts:ident => $call:expr) => {
154        match ($self.limit, $self.endian) {
155            (Unlimited, Little) => {
156                let $opts = DefaultOptions::new().with_no_limit().with_little_endian();
157                $call
158            }
159            (Unlimited, Big) => {
160                let $opts = DefaultOptions::new().with_no_limit().with_big_endian();
161                $call
162            }
163            (Unlimited, Native) => {
164                let $opts = DefaultOptions::new().with_no_limit().with_native_endian();
165                $call
166            }
167
168            (Limited(l), Little) => {
169                let $opts = DefaultOptions::new().with_limit(l).with_little_endian();
170                $call
171            }
172            (Limited(l), Big) => {
173                let $opts = DefaultOptions::new().with_limit(l).with_big_endian();
174                $call
175            }
176            (Limited(l), Native) => {
177                let $opts = DefaultOptions::new().with_limit(l).with_native_endian();
178                $call
179            }
180        }
181    };
182}
183
184impl Config {
185    #[inline(always)]
186    pub(crate) fn new() -> Config {
187        Config {
188            limit: LimitOption::Unlimited,
189            endian: EndianOption::Little,
190        }
191    }
192
193    /// Sets the byte limit to be unlimited.
194    /// This is the default.
195    #[inline(always)]
196    pub fn no_limit(&mut self) -> &mut Self {
197        self.limit = LimitOption::Unlimited;
198        self
199    }
200
201    /// Sets the byte limit to `limit`.
202    #[inline(always)]
203    pub fn limit(&mut self, limit: u64) -> &mut Self {
204        self.limit = LimitOption::Limited(limit);
205        self
206    }
207
208    /// Sets the endianness to little-endian
209    /// This is the default.
210    #[inline(always)]
211    pub fn little_endian(&mut self) -> &mut Self {
212        self.endian = EndianOption::Little;
213        self
214    }
215
216    /// Sets the endianness to big-endian
217    #[inline(always)]
218    pub fn big_endian(&mut self) -> &mut Self {
219        self.endian = EndianOption::Big;
220        self
221    }
222
223    /// Sets the endianness to the the machine-native endianness
224    #[inline(always)]
225    pub fn native_endian(&mut self) -> &mut Self {
226        self.endian = EndianOption::Native;
227        self
228    }
229
230    /// Serializes a serializable object into a `Vec` of bytes using this configuration
231    #[inline(always)]
232    pub fn serialize<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<Vec<u8>> {
233        config_map!(self, opts => ::internal::serialize(t, opts))
234    }
235
236    /// Returns the size that an object would be if serialized using Bincode with this configuration
237    #[inline(always)]
238    pub fn serialized_size<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<u64> {
239        config_map!(self, opts => ::internal::serialized_size(t, opts))
240    }
241
242    /// Serializes an object directly into a `Writer` using this configuration
243    ///
244    /// If the serialization would take more bytes than allowed by the size limit, an error
245    /// is returned and *no bytes* will be written into the `Writer`
246    #[inline(always)]
247    pub fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(
248        &self,
249        w: W,
250        t: &T,
251    ) -> Result<()> {
252        config_map!(self, opts => ::internal::serialize_into(w, t, opts))
253    }
254
255    /// Deserializes a slice of bytes into an instance of `T` using this configuration
256    #[inline(always)]
257    pub fn deserialize<'a, T: serde::Deserialize<'a>>(&self, bytes: &'a [u8]) -> Result<T> {
258        config_map!(self, opts => ::internal::deserialize(bytes, opts))
259    }
260
261    /// TODO: document
262    #[doc(hidden)]
263    #[inline(always)]
264    pub fn deserialize_in_place<'a, R, T>(&self, reader: R, place: &mut T) -> Result<()>
265    where
266        R: BincodeRead<'a>,
267        T: serde::de::Deserialize<'a>,
268    {
269        config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place))
270    }
271
272    /// Deserializes a slice of bytes with state `seed` using this configuration.
273    #[inline(always)]
274    pub fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
275        &self,
276        seed: T,
277        bytes: &'a [u8],
278    ) -> Result<T::Value> {
279        config_map!(self, opts => ::internal::deserialize_seed(seed, bytes, opts))
280    }
281
282    /// Deserializes an object directly from a `Read`er using this configuration
283    ///
284    /// If this returns an `Error`, `reader` may be in an invalid state.
285    #[inline(always)]
286    pub fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(
287        &self,
288        reader: R,
289    ) -> Result<T> {
290        config_map!(self, opts => ::internal::deserialize_from(reader, opts))
291    }
292
293    /// Deserializes an object from a custom `BincodeRead`er using the default configuration.
294    /// It is highly recommended to use `deserialize_from` unless you need to implement
295    /// `BincodeRead` for performance reasons.
296    ///
297    /// If this returns an `Error`, `reader` may be in an invalid state.
298    #[inline(always)]
299    pub fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
300        &self,
301        reader: R,
302    ) -> Result<T> {
303        config_map!(self, opts => ::internal::deserialize_from_custom(reader, opts))
304    }
305
306    /// Executes the acceptor with a serde::Deserializer instance.
307    /// NOT A PART OF THE STABLE PUBLIC API
308    #[doc(hidden)]
309    pub fn with_deserializer<'a, A, R>(&self, reader: R, acceptor: A) -> A::Output
310    where
311        A: DeserializerAcceptor<'a>,
312        R: BincodeRead<'a>,
313    {
314        config_map!(self, opts => {
315            let mut deserializer = ::de::Deserializer::new(reader, opts);
316            acceptor.accept(&mut deserializer)
317        })
318    }
319
320    /// Executes the acceptor with a serde::Serializer instance.
321    /// NOT A PART OF THE STABLE PUBLIC API
322    #[doc(hidden)]
323    pub fn with_serializer<A, W>(&self, writer: W, acceptor: A) -> A::Output
324    where
325        A: SerializerAcceptor,
326        W: Write,
327    {
328        config_map!(self, opts => {
329            let mut serializer = ::ser::Serializer::new(writer, opts);
330            acceptor.accept(&mut serializer)
331        })
332    }
333}