1 use std::io::{Read, Write};
2 
3 use self::EndianOption::*;
4 use self::LimitOption::*;
5 use super::{DefaultOptions, Options};
6 use de::read::BincodeRead;
7 use error::Result;
8 use serde;
9 
10 /// A configuration builder whose options Bincode will use
11 /// while serializing and deserializing.
12 ///
13 /// ### Options
14 /// Endianness: The endianness with which multi-byte integers will be read/written.  *default: little endian*
15 /// Limit: The maximum number of bytes that will be read/written in a bincode serialize/deserialize. *default: unlimited*
16 ///
17 /// ### Byte Limit Details
18 /// The purpose of byte-limiting is to prevent Denial-Of-Service attacks whereby malicious attackers get bincode
19 /// deserialization to crash your process by allocating too much memory or keeping a connection open for too long.
20 ///
21 /// When a byte limit is set, bincode will return `Err` on any deserialization that goes over the limit, or any
22 /// serialization that goes over the limit.
23 #[derive(Clone, Debug)]
24 #[deprecated(
25     since = "1.3.0",
26     note = "please use the `DefaultOptions`/`Options` system instead"
27 )]
28 pub struct Config {
29     limit: LimitOption,
30     endian: EndianOption,
31 }
32 
33 #[derive(Clone, Copy, Debug)]
34 enum LimitOption {
35     Unlimited,
36     Limited(u64),
37 }
38 
39 #[derive(Clone, Copy, Debug)]
40 enum EndianOption {
41     Big,
42     Little,
43     Native,
44 }
45 
46 macro_rules! config_map {
47     ($self:expr, $opts:ident => $call:expr) => {
48         match ($self.limit, $self.endian) {
49             (Unlimited, Little) => {
50                 let $opts = DefaultOptions::new()
51                     .with_fixint_encoding()
52                     .allow_trailing_bytes()
53                     .with_no_limit()
54                     .with_little_endian();
55                 $call
56             }
57             (Unlimited, Big) => {
58                 let $opts = DefaultOptions::new()
59                     .with_fixint_encoding()
60                     .allow_trailing_bytes()
61                     .with_no_limit()
62                     .with_big_endian();
63                 $call
64             }
65             (Unlimited, Native) => {
66                 let $opts = DefaultOptions::new()
67                     .with_fixint_encoding()
68                     .allow_trailing_bytes()
69                     .with_no_limit()
70                     .with_native_endian();
71                 $call
72             }
73 
74             (Limited(l), Little) => {
75                 let $opts = DefaultOptions::new()
76                     .with_fixint_encoding()
77                     .allow_trailing_bytes()
78                     .with_limit(l)
79                     .with_little_endian();
80                 $call
81             }
82             (Limited(l), Big) => {
83                 let $opts = DefaultOptions::new()
84                     .with_fixint_encoding()
85                     .allow_trailing_bytes()
86                     .with_limit(l)
87                     .with_big_endian();
88                 $call
89             }
90             (Limited(l), Native) => {
91                 let $opts = DefaultOptions::new()
92                     .with_fixint_encoding()
93                     .allow_trailing_bytes()
94                     .with_limit(l)
95                     .with_native_endian();
96                 $call
97             }
98         }
99     };
100 }
101 
102 impl Config {
103     #[inline(always)]
new() -> Config104     pub(crate) fn new() -> Config {
105         Config {
106             limit: LimitOption::Unlimited,
107             endian: EndianOption::Little,
108         }
109     }
110 
111     /// Sets the byte limit to be unlimited.
112     /// This is the default.
113     #[inline(always)]
no_limit(&mut self) -> &mut Self114     pub fn no_limit(&mut self) -> &mut Self {
115         self.limit = LimitOption::Unlimited;
116         self
117     }
118 
119     /// Sets the byte limit to `limit`.
120     #[inline(always)]
limit(&mut self, limit: u64) -> &mut Self121     pub fn limit(&mut self, limit: u64) -> &mut Self {
122         self.limit = LimitOption::Limited(limit);
123         self
124     }
125 
126     /// Sets the endianness to little-endian
127     /// This is the default.
128     #[inline(always)]
little_endian(&mut self) -> &mut Self129     pub fn little_endian(&mut self) -> &mut Self {
130         self.endian = EndianOption::Little;
131         self
132     }
133 
134     /// Sets the endianness to big-endian
135     #[inline(always)]
big_endian(&mut self) -> &mut Self136     pub fn big_endian(&mut self) -> &mut Self {
137         self.endian = EndianOption::Big;
138         self
139     }
140 
141     /// Sets the endianness to the the machine-native endianness
142     #[inline(always)]
native_endian(&mut self) -> &mut Self143     pub fn native_endian(&mut self) -> &mut Self {
144         self.endian = EndianOption::Native;
145         self
146     }
147 
148     /// Serializes a serializable object into a `Vec` of bytes using this configuration
149     #[inline(always)]
serialize<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<Vec<u8>>150     pub fn serialize<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<Vec<u8>> {
151         config_map!(self, opts => ::internal::serialize(t, opts))
152     }
153 
154     /// Returns the size that an object would be if serialized using Bincode with this configuration
155     #[inline(always)]
serialized_size<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<u64>156     pub fn serialized_size<T: ?Sized + serde::Serialize>(&self, t: &T) -> Result<u64> {
157         config_map!(self, opts => ::internal::serialized_size(t, opts))
158     }
159 
160     /// Serializes an object directly into a `Writer` using this configuration
161     ///
162     /// If the serialization would take more bytes than allowed by the size limit, an error
163     /// is returned and *no bytes* will be written into the `Writer`
164     #[inline(always)]
serialize_into<W: Write, T: ?Sized + serde::Serialize>( &self, w: W, t: &T, ) -> Result<()>165     pub fn serialize_into<W: Write, T: ?Sized + serde::Serialize>(
166         &self,
167         w: W,
168         t: &T,
169     ) -> Result<()> {
170         config_map!(self, opts => ::internal::serialize_into(w, t, opts))
171     }
172 
173     /// Deserializes a slice of bytes into an instance of `T` using this configuration
174     #[inline(always)]
deserialize<'a, T: serde::Deserialize<'a>>(&self, bytes: &'a [u8]) -> Result<T>175     pub fn deserialize<'a, T: serde::Deserialize<'a>>(&self, bytes: &'a [u8]) -> Result<T> {
176         config_map!(self, opts => ::internal::deserialize(bytes, opts))
177     }
178 
179     /// TODO: document
180     #[doc(hidden)]
181     #[inline(always)]
deserialize_in_place<'a, R, T>(&self, reader: R, place: &mut T) -> Result<()> where R: BincodeRead<'a>, T: serde::de::Deserialize<'a>,182     pub fn deserialize_in_place<'a, R, T>(&self, reader: R, place: &mut T) -> Result<()>
183     where
184         R: BincodeRead<'a>,
185         T: serde::de::Deserialize<'a>,
186     {
187         config_map!(self, opts => ::internal::deserialize_in_place(reader, opts, place))
188     }
189 
190     /// Deserializes a slice of bytes with state `seed` using this configuration.
191     #[inline(always)]
deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>( &self, seed: T, bytes: &'a [u8], ) -> Result<T::Value>192     pub fn deserialize_seed<'a, T: serde::de::DeserializeSeed<'a>>(
193         &self,
194         seed: T,
195         bytes: &'a [u8],
196     ) -> Result<T::Value> {
197         config_map!(self, opts => ::internal::deserialize_seed(seed, bytes, opts))
198     }
199 
200     /// Deserializes an object directly from a `Read`er using this configuration
201     ///
202     /// If this returns an `Error`, `reader` may be in an invalid state.
203     #[inline(always)]
deserialize_from<R: Read, T: serde::de::DeserializeOwned>( &self, reader: R, ) -> Result<T>204     pub fn deserialize_from<R: Read, T: serde::de::DeserializeOwned>(
205         &self,
206         reader: R,
207     ) -> Result<T> {
208         config_map!(self, opts => ::internal::deserialize_from(reader, opts))
209     }
210 
211     /// Deserializes an object directly from a `Read`er with state `seed` using this configuration
212     ///
213     /// If this returns an `Error`, `reader` may be in an invalid state.
214     #[inline(always)]
deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>( &self, seed: T, reader: R, ) -> Result<T::Value>215     pub fn deserialize_from_seed<'a, R: Read, T: serde::de::DeserializeSeed<'a>>(
216         &self,
217         seed: T,
218         reader: R,
219     ) -> Result<T::Value> {
220         config_map!(self, opts => ::internal::deserialize_from_seed(seed, reader, opts))
221     }
222 
223     /// Deserializes an object from a custom `BincodeRead`er using the default configuration.
224     /// It is highly recommended to use `deserialize_from` unless you need to implement
225     /// `BincodeRead` for performance reasons.
226     ///
227     /// If this returns an `Error`, `reader` may be in an invalid state.
228     #[inline(always)]
deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>( &self, reader: R, ) -> Result<T>229     pub fn deserialize_from_custom<'a, R: BincodeRead<'a>, T: serde::de::DeserializeOwned>(
230         &self,
231         reader: R,
232     ) -> Result<T> {
233         config_map!(self, opts => ::internal::deserialize_from_custom(reader, opts))
234     }
235 
236     /// Deserializes an object from a custom `BincodeRead`er with state `seed` using the default
237     /// configuration. It is highly recommended to use `deserialize_from` unless you need to
238     /// implement `BincodeRead` for performance reasons.
239     ///
240     /// If this returns an `Error`, `reader` may be in an invalid state.
241     #[inline(always)]
deserialize_from_custom_seed< 'a, R: BincodeRead<'a>, T: serde::de::DeserializeSeed<'a>, >( &self, seed: T, reader: R, ) -> Result<T::Value>242     pub fn deserialize_from_custom_seed<
243         'a,
244         R: BincodeRead<'a>,
245         T: serde::de::DeserializeSeed<'a>,
246     >(
247         &self,
248         seed: T,
249         reader: R,
250     ) -> Result<T::Value> {
251         config_map!(self, opts => ::internal::deserialize_from_custom_seed(seed, reader, opts))
252     }
253 }
254