1use std::io::{Read, Write};
2
3use self::EndianOption::*;
4use self::LimitOption::*;
5use super::{DefaultOptions, Options};
6use de::read::BincodeRead;
7use error::Result;
8use 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)]
28pub struct Config {
29 limit: LimitOption,
30 endian: EndianOption,
31}
32
33#[derive(Clone, Copy, Debug)]
34enum LimitOption {
35 Unlimited,
36 Limited(u64),
37}
38
39#[derive(Clone, Copy, Debug)]
40enum EndianOption {
41 Big,
42 Little,
43 Native,
44}
45
46macro_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
102impl Config {
103 #[inline(always)]
104 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)]
114 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)]
121 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)]
129 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)]
136 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)]
143 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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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)]
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