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