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

    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);

    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

The concrete Reader type

The concrete Config type

Required Methods

Returns a mutable reference to the reader

Returns a reference to the config

Claim that n bytes are going to be read from the decoder. This can be used to validate Configuration::Limit<N>().

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

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

Implementors