Trait bincode::de::Decoder

source ·
pub trait Decoder: Sealed {
    type R: Reader;
    type C: Config;

    // Required methods
    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 method
    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

Required Methods§

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<T: Decode> Decode for Container<T> {
    fn decode<D: Decoder>(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, T: bincode::BorrowDecode<'de>> bincode::BorrowDecode<'de> for Container<T> {
    fn borrow_decode<D: bincode::de::BorrowDecoder<'de>>(
        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 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

Implementations on Foreign Types§

source§

impl<'a, T> Decoder for &'a mut Twhere T: Decoder,

§

type R = <T as Decoder>::R

§

type C = <T as Decoder>::C

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)

Implementors§

source§

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

§

type R = R

§

type C = C