pub trait Decoder: Sealed {
type R: Reader;
type C: Config;
type Context;
// Required methods
fn context(&mut self) -> &mut Self::Context;
fn reader(&mut self) -> &mut Self::R;
fn config(&self) -> &Self::C;
fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>;
fn unclaim_bytes_read(&mut self, n: usize);
// Provided methods
fn with_context<C>(&mut self, context: C) -> WithContext<'_, Self, C> { ... }
fn claim_container_read<T>(&mut self, len: usize) -> Result<(), DecodeError> { ... }
}Expand description
Any source that can decode basic types. This type is most notably implemented for Decoder.
Required Associated Types§
Required Methods§
Sourcefn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>
fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>
Claim that n bytes are going to be read from the decoder.
This can be used to validate Configuration::Limit<N>().
Sourcefn unclaim_bytes_read(&mut self, n: usize)
fn unclaim_bytes_read(&mut self, n: usize)
Notify the decoder that n bytes are being reclaimed.
When decoding container types, a typical implementation would claim to read len * size_of::<T>() bytes.
This is to ensure that bincode won’t allocate several GB of memory while constructing the container.
Because the implementation claims len * size_of::<T>(), but then has to decode each T, this would be marked
as double. This function allows us to un-claim each T that gets decoded.
We cannot check if len * size_of::<T>() is valid without claiming it, because this would mean that if you have
a nested container (e.g. Vec<Vec<T>>), it does not know how much memory is already claimed, and could easily
allocate much more than the user intends.
impl<Context, T: Decode<Context>> Decode<Context> for Container<T> {
fn decode<D: Decoder<Context = Context>>(decoder: &mut D) -> Result<Self, DecodeError> {
let len = u64::decode(decoder)?;
let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
// Make sure we don't allocate too much memory
decoder.claim_bytes_read(len * core::mem::size_of::<T>());
let mut result = Container::with_capacity(len);
for _ in 0..len {
// un-claim the memory
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
result.push(T::decode(decoder)?)
}
Ok(result)
}
}
impl<'de, Context, T: bincode::BorrowDecode<'de, Context>> bincode::BorrowDecode<'de, Context> for Container<T> {
fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
decoder: &mut D,
) -> core::result::Result<Self, bincode::error::DecodeError> {
let len = u64::borrow_decode(decoder)?;
let len: usize = len.try_into().map_err(|_| DecodeError::OutsideUsizeRange(len))?;
// Make sure we don't allocate too much memory
decoder.claim_bytes_read(len * core::mem::size_of::<T>());
let mut result = Container::with_capacity(len);
for _ in 0..len {
// un-claim the memory
decoder.unclaim_bytes_read(core::mem::size_of::<T>());
result.push(T::borrow_decode(decoder)?)
}
Ok(result)
}
}Provided Methods§
Sourcefn with_context<C>(&mut self, context: C) -> WithContext<'_, Self, C>
fn with_context<C>(&mut self, context: C) -> WithContext<'_, Self, C>
Wraps decoder with a context
Sourcefn claim_container_read<T>(&mut self, len: usize) -> Result<(), DecodeError>
fn claim_container_read<T>(&mut self, len: usize) -> Result<(), DecodeError>
Claim that we’re going to read a container which contains len entries of T.
This will correctly handle overflowing if len * size_of::<T>() > usize::max_value
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.