bincode_next/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_next::Decode<Context> for Entity {
53///     fn decode<D: bincode_next::de::Decoder<Context = Context>>(
54///         decoder: &mut D,
55///     ) -> core::result::Result<Self, bincode_next::error::DecodeError> {
56///         Ok(Self {
57///             x: bincode_next::Decode::decode(decoder)?,
58///             y: bincode_next::Decode::decode(decoder)?,
59///         })
60///     }
61/// }
62/// impl<'de, Context> bincode_next::BorrowDecode<'de, Context> for Entity {
63///     fn borrow_decode<D: bincode_next::de::BorrowDecoder<'de, Context = Context>>(
64///         decoder: &mut D,
65///     ) -> core::result::Result<Self, bincode_next::error::DecodeError> {
66///         Ok(Self {
67///             x: bincode_next::BorrowDecode::borrow_decode(decoder)?,
68///             y: bincode_next::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_next::Decode<Context> for Foo {
80/// #     fn decode<D: bincode_next::de::Decoder<Context = Context>>(
81/// #         decoder: &mut D,
82/// #     ) -> core::result::Result<Self, bincode_next::error::DecodeError> {
83/// let x: u8 = bincode_next::Decode::<Context>::decode(decoder)?;
84/// let x = <u8 as bincode_next::Decode::<Context>>::decode(decoder)?;
85/// #         Ok(Foo)
86/// #     }
87/// # }
88/// # bincode_next::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_next::de::Decoder;
95/// use bincode_next::error::DecodeError;
96/// struct BytesInArena<'a>(bumpalo::collections::Vec<'a, u8>);
97/// impl<'a> bincode_next::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    ///
106    /// # Errors
107    ///
108    /// Returns any error encountered during decoding.
109    fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError>;
110}
111
112/// Trait that makes a type able to be decoded, akin to serde's `Deserialize` trait.
113///
114/// 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.
115///
116/// This trait will be automatically implemented if you enable the `derive` feature and add `#[derive(bincode::Decode)]` to a type with a lifetime.
117pub trait BorrowDecode<'de, Context>: Sized {
118    /// Attempt to decode this type with the given [`BorrowDecode`\].
119    ///
120    /// # Errors
121    ///
122    /// Returns any error encountered during decoding.
123    fn borrow_decode<D: BorrowDecoder<'de, Context = Context>>(
124        decoder: &mut D,
125    ) -> Result<Self, DecodeError>;
126}
127
128/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`.
129#[macro_export]
130macro_rules! impl_borrow_decode {
131    ($ty:ty $(, $param:tt)*) => {
132        impl<'de $(, $param)*, __Context> $crate::BorrowDecode<'de, __Context> for $ty {
133            fn borrow_decode<D: $crate::de::BorrowDecoder<'de, Context = __Context>>(
134                decoder: &mut D,
135            ) -> core::result::Result<Self, $crate::error::DecodeError> {
136                $crate::Decode::decode(decoder)
137            }
138        }
139    };
140}
141
142/// Helper macro to implement `BorrowDecode` for any type that implements `Decode`.
143#[macro_export]
144macro_rules! impl_borrow_decode_with_context {
145    ($ty:ty, $context:ty $(, $param:tt)*) => {
146        impl<'de $(, $param)*> $crate::BorrowDecode<'de, $context> for $ty {
147            fn borrow_decode<D: $crate::de::BorrowDecoder<'de, Context = $context>>(
148                decoder: &mut D,
149            ) -> core::result::Result<Self, $crate::error::DecodeError> {
150                $crate::Decode::decode(decoder)
151            }
152        }
153    };
154}
155
156/// Any source that can decode basic types. This type is most notably implemented for [Decoder].
157pub trait Decoder: Sealed {
158    /// The concrete [Reader] type
159    type R: Reader;
160
161    /// The concrete [Config] type
162    type C: Config;
163
164    /// The decoding context type
165    type Context;
166
167    /// Returns the decoding context
168    fn context(&mut self) -> &mut Self::Context;
169
170    /// Wraps decoder with a context
171    fn with_context<C>(&mut self, context: C) -> WithContext<'_, Self, C> {
172        WithContext {
173            decoder: self,
174            context,
175        }
176    }
177
178    /// Returns a mutable reference to the reader
179    fn reader(&mut self) -> &mut Self::R;
180
181    /// Returns a reference to the config
182    fn config(&self) -> &Self::C;
183
184    /// Claim that `n` bytes are going to be read from the decoder.
185    /// This can be used to validate `Configuration::Limit<N>()`.
186    ///
187    /// # Errors
188    ///
189    /// Returns `DecodeError::LimitExceeded` if the limit is exceeded.
190    fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>;
191
192    /// Claim that we're going to read a container which contains `len` entries of `T`.
193    /// This will correctly handle overflowing if `len * size_of::<T>() > usize::max_value`
194    ///
195    /// # Errors
196    ///
197    /// Returns `DecodeError::LimitExceeded` if the limit is exceeded or if `len * size_of::<T>()` overflows.
198    fn claim_container_read<T>(&mut self, len: usize) -> Result<(), DecodeError> {
199        if <Self::C as InternalLimitConfig>::LIMIT.is_some() {
200            len.checked_mul(core::mem::size_of::<T>())
201                .map_or(Err(DecodeError::LimitExceeded), |val| {
202                    self.claim_bytes_read(val)
203                })
204        } else {
205            Ok(())
206        }
207    }
208
209    /// Notify the decoder that `n` bytes are being reclaimed.
210    ///
211    /// When decoding container types, a typical implementation would claim to read `len * size_of::<T>()` bytes.
212    /// This is to ensure that bincode won't allocate several GB of memory while constructing the container.
213    ///
214    /// Because the implementation claims `len * size_of::<T>()`, but then has to decode each `T`, this would be marked
215    /// as double. This function allows us to un-claim each `T` that gets decoded.
216    ///
217    /// We cannot check if `len * size_of::<T>()` is valid without claiming it, because this would mean that if you have
218    /// a nested container (e.g. `Vec<Vec<T>>`), it does not know how much memory is already claimed, and could easily
219    /// allocate much more than the user intends.
220    /// ```
221    /// # use bincode_next::de::{Decode, Decoder};
222    /// # use bincode_next::error::DecodeError;
223    /// # struct Container<T>(Vec<T>);
224    /// # impl<T> Container<T> {
225    /// #     fn with_capacity(cap: usize) -> Self {
226    /// #         Self(Vec::with_capacity(cap))
227    /// #     }
228    /// #     
229    /// #     fn push(&mut self, t: T) {
230    /// #         self.0.push(t);
231    /// #     }
232    /// # }
233    /// impl<Context, T: Decode<Context>> Decode<Context> for Container<T> {
234    ///     fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
235    ///         let len = u64::decode(decoder)?;
236    ///         let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
237    ///         // Make sure we don't allocate too much memory
238    ///         decoder.claim_bytes_read(len * core::mem::size_of::<T>());
239    ///
240    ///         let mut result = Container::with_capacity(len);
241    ///         for _ in 0..len {
242    ///             // un-claim the memory
243    ///             decoder.unclaim_bytes_read(core::mem::size_of::<T>());
244    ///             result.push(T::decode(decoder)?)
245    ///         }
246    ///         Ok(result)
247    ///     }
248    /// }
249    /// impl<'de, Context, T: bincode_next::BorrowDecode<'de, Context>> bincode_next::BorrowDecode<'de, Context> for Container<T> {
250    ///     fn borrow_decode<D: bincode_next::de::BorrowDecoder<'de, Context = Context>>(
251    ///         decoder: &mut D,
252    ///     ) -> core::result::Result<Self, bincode_next::error::DecodeError> {
253    ///         let len = u64::borrow_decode(decoder)?;
254    ///         let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
255    ///         // Make sure we don't allocate too much memory
256    ///         decoder.claim_bytes_read(len * core::mem::size_of::<T>());
257    ///
258    ///         let mut result = Container::with_capacity(len);
259    ///         for _ in 0..len {
260    ///             // un-claim the memory
261    ///             decoder.unclaim_bytes_read(core::mem::size_of::<T>());
262    ///             result.push(T::borrow_decode(decoder)?)
263    ///         }
264    ///         Ok(result)
265    ///     }
266    /// }
267    /// ```
268    fn unclaim_bytes_read(&mut self, n: usize);
269}
270
271/// Any source that can decode basic types. This type is most notably implemented for [Decoder].
272///
273/// This is an extension of [Decode] that can also return borrowed data.
274pub trait BorrowDecoder<'de>: Decoder {
275    /// The concrete [`BorrowReader`\] type
276    type BR: BorrowReader<'de>;
277
278    /// Returns a mutable reference to the borrow reader
279    fn borrow_reader(&mut self) -> &mut Self::BR;
280}
281
282impl<T> Decoder for &mut T
283where
284    T: Decoder,
285{
286    type R = T::R;
287
288    type C = T::C;
289
290    type Context = T::Context;
291
292    fn reader(&mut self) -> &mut Self::R {
293        T::reader(self)
294    }
295
296    fn config(&self) -> &Self::C {
297        T::config(self)
298    }
299
300    #[inline]
301    fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError> {
302        T::claim_bytes_read(self, n)
303    }
304
305    #[inline]
306    fn unclaim_bytes_read(&mut self, n: usize) {
307        T::unclaim_bytes_read(self, n);
308    }
309
310    fn context(&mut self) -> &mut Self::Context {
311        T::context(self)
312    }
313}
314
315impl<'de, T> BorrowDecoder<'de> for &mut T
316where
317    T: BorrowDecoder<'de>,
318{
319    type BR = T::BR;
320
321    fn borrow_reader(&mut self) -> &mut Self::BR {
322        T::borrow_reader(self)
323    }
324}
325
326/// Decodes only the option variant from the decoder. Will not read any more data than that.
327#[inline]
328pub(crate) fn decode_option_variant<D: Decoder>(
329    decoder: &mut D,
330    type_name: &'static str,
331) -> Result<Option<()>, DecodeError> {
332    let is_some = u8::decode(decoder)?;
333    match is_some {
334        0 => Ok(None),
335        1 => Ok(Some(())),
336        x => Err(DecodeError::UnexpectedVariant {
337            found: u32::from(x),
338            allowed: &crate::error::AllowedEnumVariants::Range { max: 1, min: 0 },
339            type_name,
340        }),
341    }
342}
343
344/// Decodes the length of any slice, container, etc from the decoder
345#[inline]
346pub(crate) fn decode_slice_len<D: Decoder>(decoder: &mut D) -> Result<usize, DecodeError> {
347    let v = u64::decode(decoder)?;
348
349    v.try_into().map_err(|_| DecodeError::OutsideUsizeRange(v))
350}