[go: up one dir, main page]

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", so this trait is not object safe.

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