Skip to main content

bincode/de/
untrusted.rs

1//! Explicit support for decoding externally supplied bytes.
2
3use super::{BorrowDecoder, Decoder};
4use crate::error::DecodeError;
5
6/// A sealed decoder accepted by the explicit untrusted decoding traits.
7///
8/// Construct one with [`super::DecoderImpl::new_untrusted`]. Context changes and
9/// mutable references preserve this capability. Collection safeguards belong to
10/// [`DecodeUntrusted`] / [`BorrowDecodeUntrusted`] implementations; invoking
11/// ordinary [`super::Decode`] explicitly retains ordinary behavior.
12pub trait UntrustedDecoder: Decoder {}
13
14/// An untrusted decoder that can also borrow from its input.
15pub trait BorrowUntrustedDecoder<'de>: BorrowDecoder<'de> + UntrustedDecoder {}
16
17impl<'de, D: BorrowDecoder<'de> + UntrustedDecoder + ?Sized> BorrowUntrustedDecoder<'de> for D {}
18
19/// Explicitly implements the untrusted decoding contract for a type.
20///
21/// This trait is independent of [`super::Decode`]. Deriving it generates only
22/// `DecodeUntrusted` and [`BorrowDecodeUntrusted`]; derive ordinary `Decode`
23/// separately if both APIs should be supported. Nested fields must implement
24/// the corresponding untrusted trait. Manual implementations are responsible
25/// for their resource use and domain validation; this is not a universal CPU,
26/// memory, or recursion budget.
27///
28/// Ordinary-only types cannot enter the untrusted API:
29/// ```compile_fail
30/// #[derive(bincode::Decode)]
31/// struct Ordinary(u8);
32/// let _ = bincode::decode_from_slice_untrusted::<Ordinary, _>(&[1], bincode::config::standard());
33/// ```
34/// Untrusted-only types cannot enter the ordinary API:
35/// ```compile_fail
36/// #[derive(bincode::DecodeUntrusted)]
37/// struct External(u8);
38/// let _ = bincode::decode_from_slice::<External, _>(&[1], bincode::config::standard());
39/// ```
40/// Derivation also checks concrete field types:
41/// ```compile_fail
42/// #[derive(bincode::Decode)]
43/// struct Ordinary(u8);
44/// #[derive(bincode::DecodeUntrusted)]
45/// struct External { field: Option<Ordinary> }
46/// ```
47/// Enum fields and map contents require the same explicit support:
48/// ```compile_fail
49/// #[derive(bincode::Decode)]
50/// struct Ordinary(u8);
51/// #[derive(bincode::DecodeUntrusted)]
52/// enum External { Map(std::collections::HashMap<u8, Ordinary>) }
53/// ```
54/// Borrowed entry points also reject ordinary-only implementations:
55/// ```compile_fail
56/// #[derive(bincode::BorrowDecode)]
57/// struct Ordinary<'a>(&'a str);
58/// let _ = bincode::borrow_decode_from_slice_untrusted::<Ordinary<'_>, _>(&[0], bincode::config::standard());
59/// ```
60/// Untrusted methods require the explicit decoder capability:
61/// ```compile_fail
62/// use bincode::DecodeUntrusted;
63/// let reader = bincode::de::read::SliceReader::new(&[1]);
64/// let mut decoder = bincode::de::DecoderImpl::new(reader, bincode::config::standard(), ());
65/// let _ = u8::decode_untrusted(&mut decoder);
66/// ```
67pub trait DecodeUntrusted<Context>: Sized {
68    /// Decode with explicit untrusted field dispatch and resource handling.
69    fn decode_untrusted<D: UntrustedDecoder<Context = Context>>(
70        decoder: &mut D,
71    ) -> Result<Self, DecodeError>;
72}
73
74/// Explicit untrusted decoding for types borrowing from their input.
75///
76/// Use `#[derive(BorrowDecodeUntrusted)]` for borrowed types. Deriving
77/// [`DecodeUntrusted`] already generates this implementation for owned types.
78pub trait BorrowDecodeUntrusted<'de, Context>: Sized {
79    /// Borrow-decode with explicit untrusted field dispatch and resource handling.
80    fn borrow_decode_untrusted<D: BorrowUntrustedDecoder<'de, Context = Context>>(
81        decoder: &mut D,
82    ) -> Result<Self, DecodeError>;
83}
84
85/// Implement borrowed untrusted decoding by delegating to an explicit owned implementation.
86#[macro_export]
87macro_rules! impl_borrow_decode_untrusted {
88    ($ty:ty $(, $param:tt)*) => {
89        impl<'de $(, $param)*, __Context> $crate::BorrowDecodeUntrusted<'de, __Context> for $ty {
90            fn borrow_decode_untrusted<D: $crate::de::BorrowUntrustedDecoder<'de, Context = __Context>>(
91                decoder: &mut D,
92            ) -> core::result::Result<Self, $crate::error::DecodeError> {
93                $crate::DecodeUntrusted::decode_untrusted(decoder)
94            }
95        }
96    };
97}