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