bincode/de/mod.rs
1//! Decoder-based structs and traits.
2
3mod decoder;
4mod impl_core;
5mod impl_tuples;
6mod impls;
7
8use self::{
9 decoder::WithContext,
10 read::{BorrowReader, Reader},
11};
12use crate::{
13 config::{Config, InternalLimitConfig},
14 error::DecodeError,
15 utils::Sealed,
16};
17
18pub mod read;
19
20pub use self::decoder::DecoderImpl;
21
22/// Trait that makes a type able to be decoded, akin to serde's `DeserializeOwned` trait.
23///
24/// Some types may require specific contexts. For example, to decode arena-based collections, an arena allocator must be provided as a context. In these cases, the context type `Context` should be specified or bounded.
25///
26/// This trait should be implemented for types which do not have references to data in the reader. For types that contain e.g. `&str` and `&[u8]`, implement [BorrowDecode] instead.
27///
28/// Whenever you derive `Decode` for your type, the base trait `BorrowDecode` is automatically implemented.
29///
30/// This trait will be automatically implemented with unbounded `Context` if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to your type. Note that if the type contains any lifetimes, `BorrowDecode` will be implemented instead.
31///
32/// # Implementing this trait manually
33///
34/// If you want to implement this trait for your type, the easiest way is to add a `#[derive(bincode::Decode)]`, build and check your `target/generated/bincode/` folder. This should generate a `<Struct name>_Decode.rs` file.
35///
36/// For this struct:
37///
38/// ```
39/// struct Entity {
40/// pub x: f32,
41/// pub y: f32,
42/// }
43/// ```
44///
45/// It will look something like:
46///
47/// ```
48/// # struct Entity {
49/// # pub x: f32,
50/// # pub y: f32,
51/// # }
52/// impl<Context> bincode::Decode<Context> for Entity {
53/// fn decode<D: bincode::de::Decoder<Context = Context>>(
54/// decoder: &mut D,
55/// ) -> core::result::Result<Self, bincode::error::DecodeError> {
56/// Ok(Self {
57/// x: bincode::Decode::decode(decoder)?,
58/// y: bincode::Decode::decode(decoder)?,
59/// })
60/// }
61/// }
62/// impl<'de, Context> bincode::BorrowDecode<'de, Context> for Entity {
63/// fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
64/// decoder: &mut D,
65/// ) -> core::result::Result<Self, bincode::error::DecodeError> {
66/// Ok(Self {
67/// x: bincode::BorrowDecode::borrow_decode(decoder)?,
68/// y: bincode::BorrowDecode::borrow_decode(decoder)?,
69/// })
70/// }
71/// }
72/// ```
73///
74/// From here you can add/remove fields, or add custom logic.
75///
76/// To get specific integer types, you can use:
77/// ```
78/// # struct Foo;
79/// # impl<Context> bincode::Decode<Context> for Foo {
80/// # fn decode<D: bincode::de::Decoder<Context = Context>>(
81/// # decoder: &mut D,
82/// # ) -> core::result::Result<Self, bincode::error::DecodeError> {
83/// let x: u8 = bincode::Decode::<Context>::decode(decoder)?;
84/// let x = <u8 as bincode::Decode::<Context>>::decode(decoder)?;
85/// # Ok(Foo)
86/// # }
87/// # }
88/// # bincode::impl_borrow_decode!(Foo);
89/// ```
90///
91/// You can use `Context` to require contexts for decoding a type:
92/// ```
93/// # /// # use bumpalo::Bump;
94/// use bincode::de::Decoder;
95/// use bincode::error::DecodeError;
96/// struct BytesInArena<'a>(bumpalo::collections::Vec<'a, u8>);
97/// impl<'a> bincode::Decode<&'a bumpalo::Bump> for BytesInArena<'a> {
98/// fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, DecodeError> {
99/// todo!()
100/// }
101/// # }
102/// ```
103pub trait Decode<Context>: Sized {
104 /// Attempt to decode this type with the given [Decode].
105 fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError>;
106}
107
108/// Trait that makes a type able to be decoded, akin to serde's `Deserialize` trait.
109///
110/// This trait should be implemented for types that contain borrowed data, like `&str` and `&[u8]`. If your type does not have borrowed data, consider implementing [Decode] instead.
111///
112/// This trait will be automatically implemented if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to a type with a lifetime.
113pub trait BorrowDecode<'de, Context>: Sized {
114 /// Attempt to decode this type with the given [BorrowDecode].
115 fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(
116 decoder: &mut D,
117 ) -> Result<Self, DecodeError>;
118}
119
120/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`.
121#[macro_export]
122macro_rules! impl_borrow_decode {
123 ($ty:ty $(, $param:tt)*) => {
124 impl<'de $(, $param)*, __Context> $crate::BorrowDecode<'de, __Context> for $ty {
125 fn borrow_decode<D: $crate::de::BorrowDecoder<'de, Context = __Context>>(
126 decoder: &mut D,
127 ) -> core::result::Result<Self, $crate::error::DecodeError> {
128 $crate::Decode::decode(decoder)
129 }
130 }
131 };
132}
133
134/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`.
135#[macro_export]
136macro_rules! impl_borrow_decode_with_context {
137 ($ty:ty, $context:ty $(, $param:tt)*) => {
138 impl<'de $(, $param)*> $crate::BorrowDecode<'de, $context> for $ty {
139 fn borrow_decode<D: $crate::de::BorrowDecoder<'de, Context = $context>>(
140 decoder: &mut D,
141 ) -> core::result::Result<Self, $crate::error::DecodeError> {
142 $crate::Decode::decode(decoder)
143 }
144 }
145 };
146}
147
148/// Any source that can decode basic types. This type is most notably implemented for [Decoder].
149pub trait Decoder: Sealed {
150 /// The concrete [Reader] type
151 type R: Reader;
152
153 /// The concrete [Config] type
154 type C: Config;
155
156 /// The decoding context type
157 type Context;
158
159 /// Returns the decoding context
160 fn context(&mut self) -> &mut Self::Context;
161
162 /// Wraps decoder with a context
163 fn with_context<C>(&mut self, context: C) -> WithContext<Self, C> {
164 WithContext {
165 decoder: self,
166 context,
167 }
168 }
169
170 /// Returns a mutable reference to the reader
171 fn reader(&mut self) -> &mut Self::R;
172
173 /// Returns a reference to the config
174 fn config(&self) -> &Self::C;
175
176 /// Claim that `n` bytes are going to be read from the decoder.
177 /// This can be used to validate `Configuration::Limit<N>()`.
178 fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>;
179
180 /// Claim that we're going to read a container which contains `len` entries of `T`.
181 /// This will correctly handle overflowing if `len * size_of::<T>() > usize::max_value`
182 fn claim_container_read<T>(&mut self, len: usize) -> Result<(), DecodeError> {
183 if <Self::C as InternalLimitConfig>::LIMIT.is_some() {
184 match len.checked_mul(core::mem::size_of::<T>()) {
185 Some(val) => self.claim_bytes_read(val),
186 None => Err(DecodeError::LimitExceeded),
187 }
188 } else {
189 Ok(())
190 }
191 }
192
193 /// Notify the decoder that `n` bytes are being reclaimed.
194 ///
195 /// When decoding container types, a typical implementation would claim to read `len * size_of::<T>()` bytes.
196 /// This is to ensure that bincode won't allocate several GB of memory while constructing the container.
197 ///
198 /// Because the implementation claims `len * size_of::<T>()`, but then has to decode each `T`, this would be marked
199 /// as double. This function allows us to un-claim each `T` that gets decoded.
200 ///
201 /// We cannot check if `len * size_of::<T>()` is valid without claiming it, because this would mean that if you have
202 /// a nested container (e.g. `Vec<Vec<T>>`), it does not know how much memory is already claimed, and could easily
203 /// allocate much more than the user intends.
204 /// ```
205 /// # use bincode::de::{Decode, Decoder};
206 /// # use bincode::error::DecodeError;
207 /// # struct Container<T>(Vec<T>);
208 /// # impl<T> Container<T> {
209 /// # fn with_capacity(cap: usize) -> Self {
210 /// # Self(Vec::with_capacity(cap))
211 /// # }
212 /// #
213 /// # fn push(&mut self, t: T) {
214 /// # self.0.push(t);
215 /// # }
216 /// # }
217 /// impl<Context, T: Decode<Context>> Decode<Context> for Container<T> {
218 /// fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
219 /// let len = u64::decode(decoder)?;
220 /// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
221 /// // Make sure we don't allocate too much memory
222 /// decoder.claim_bytes_read(len * core::mem::size_of::<T>());
223 ///
224 /// let mut result = Container::with_capacity(len);
225 /// for _ in 0..len {
226 /// // un-claim the memory
227 /// decoder.unclaim_bytes_read(core::mem::size_of::<T>());
228 /// result.push(T::decode(decoder)?)
229 /// }
230 /// Ok(result)
231 /// }
232 /// }
233 /// impl<'de, Context, T: bincode::BorrowDecode<'de, Context>> bincode::BorrowDecode<'de, Context> for Container<T> {
234 /// fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
235 /// decoder: &mut D,
236 /// ) -> core::result::Result<Self, bincode::error::DecodeError> {
237 /// let len = u64::borrow_decode(decoder)?;
238 /// let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
239 /// // Make sure we don't allocate too much memory
240 /// decoder.claim_bytes_read(len * core::mem::size_of::<T>());
241 ///
242 /// let mut result = Container::with_capacity(len);
243 /// for _ in 0..len {
244 /// // un-claim the memory
245 /// decoder.unclaim_bytes_read(core::mem::size_of::<T>());
246 /// result.push(T::borrow_decode(decoder)?)
247 /// }
248 /// Ok(result)
249 /// }
250 /// }
251 /// ```
252 fn unclaim_bytes_read(&mut self, n: usize);
253}
254
255/// Any source that can decode basic types. This type is most notably implemented for [Decoder].
256///
257/// This is an extension of [Decode] that can also return borrowed data.
258pub trait BorrowDecoder<'de>: Decoder {
259 /// The concrete [BorrowReader] type
260 type BR: BorrowReader<'de>;
261
262 /// Rerturns a mutable reference to the borrow reader
263 fn borrow_reader(&mut self) -> &mut Self::BR;
264}
265
266impl<T> Decoder for &mut T
267where
268 T: Decoder,
269{
270 type R = T::R;
271
272 type C = T::C;
273
274 type Context = T::Context;
275
276 fn reader(&mut self) -> &mut Self::R {
277 T::reader(self)
278 }
279
280 fn config(&self) -> &Self::C {
281 T::config(self)
282 }
283
284 #[inline]
285 fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> {
286 T::claim_bytes_read(self, n)
287 }
288
289 #[inline]
290 fn unclaim_bytes_read(&mut self, n: usize) {
291 T::unclaim_bytes_read(self, n)
292 }
293
294 fn context(&mut self) -> &mut Self::Context {
295 T::context(self)
296 }
297}
298
299impl<'de, T> BorrowDecoder<'de> for &mut T
300where
301 T: BorrowDecoder<'de>,
302{
303 type BR = T::BR;
304
305 fn borrow_reader(&mut self) -> &mut Self::BR {
306 T::borrow_reader(self)
307 }
308}
309
310/// Decodes only the option variant from the decoder. Will not read any more data than that.
311#[inline]
312pub(crate) fn decode_option_variant<D: Decoder>(
313 decoder: &mut D,
314 type_name: &'static str,
315) -> Result<Option<()>, DecodeError> {
316 let is_some = u8::decode(decoder)?;
317 match is_some {
318 0 => Ok(None),
319 1 => Ok(Some(())),
320 x => Err(DecodeError::UnexpectedVariant {
321 found: x as u32,
322 allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
323 type_name,
324 }),
325 }
326}
327
328/// Decodes the length of any slice, container, etc from the decoder
329#[inline]
330pub(crate) fn decode_slice_len<D: Decoder>(decoder: &mut D) -> Result<usize, DecodeError> {
331 let v = u64::decode(decoder)?;
332
333 v.try_into().map_err(|_| DecodeError::OutsideUsizeRange(v))
334}