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}