Skip to main content

Decoder

Trait Decoder 

Source
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§

Source

type R: Reader

The concrete Reader type

Source

type C: Config

The concrete Config type

Source

type Context

The decoding context type

Required Methods§

Source

fn context(&mut self) -> &mut Self::Context

Returns the decoding context

Source

fn reader(&mut self) -> &mut Self::R

Returns a mutable reference to the reader

Source

fn config(&self) -> &Self::C

Returns a reference to the config

Source

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>().

Source

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§

Source

fn with_context<C>(&mut self, context: C) -> WithContext<'_, Self, C>

Wraps decoder with a context

Source

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".

Implementations on Foreign Types§

Source§

impl<T> Decoder for &mut T
where T: Decoder,

Source§

type R = <T as Decoder>::R

Source§

type C = <T as Decoder>::C

Source§

type Context = <T as Decoder>::Context

Source§

fn reader(&mut self) -> &mut Self::R

Source§

fn config(&self) -> &Self::C

Source§

fn claim_bytes_read(&mut self, n: usize) -> Result<(), DecodeError>

Source§

fn unclaim_bytes_read(&mut self, n: usize)

Source§

fn context(&mut self) -> &mut Self::Context

Implementors§

Source§

impl<R: Reader, C: Config, Context> Decoder for DecoderImpl<R, C, Context>

Source§

type R = R

Source§

type C = C

Source§

type Context = Context