Trait push_decode::Decoder

source ·
pub trait Decoder: Sized {
    type Value;
    type Error;

    // Required methods
    fn decode_chunk(&mut self, bytes: &mut &[u8]) -> Result<(), Self::Error>;
    fn end(self) -> Result<Self::Value, Self::Error>;

    // Provided methods
    fn bytes_received(&mut self, bytes: &[u8]) -> Result<usize, Self::Error> { ... }
    fn then<R: Decoder, F: FnOnce(Self::Value) -> R>(
        self,
        fun: F
    ) -> Then<Self, R, F> { ... }
    fn then_try<E, R: Decoder, F: FnOnce(Self::Value) -> Result<R, E>>(
        self,
        fun: F
    ) -> ThenTry<E, Self, R, F>
       where E: From<Self::Error> + From<R::Error> { ... }
    fn chain<D: Decoder>(self, following: D) -> Chain<Self, D> { ... }
    fn take(&mut self) -> Result<Self::Value, Self::Error>
       where Self: Default { ... }
    fn sub_decode<E, F: FnMut(Self::Error) -> E>(
        &mut self,
        bytes: &mut &[u8],
        map_err: F
    ) -> ControlFlow<Result<(), E>, Self::Value>
       where Self: Default { ... }
    fn wrap_sub_decode<F: FnOnce() -> ControlFlow<Result<(), Self::Error>, Infallible>>(
        f: F
    ) -> Result<(), Self::Error> { ... }
}
Expand description

Represents types responsible for decoding bytes pushed into it.

The types implementing this trait act like state machines (similar to futures) but instead of pulling data from some internal source they receive it in method calls. So they are actually much closer to the traditional state machines than futures.

Required Associated Types§

source

type Value

The type of value produced by this decoder.

source

type Error

Decoding error.

Required Methods§

source

fn decode_chunk(&mut self, bytes: &mut &[u8]) -> Result<(), Self::Error>

Processes nex chunk of bytes and updates the cursor.

The decoder has to processes the chunk of bytes performing validation and transformation.

If the bytes are valid the slice is updated to point to unread part. Thus if the slice is non-epty after this method returns the decoder ended decoding.

Errors

An error is returned in case the bytes are invalid. The validity is defined by the implementor.

No error may be returned if the number of bytes passed is not sufficient to decode the value - the remaining bytes will be passed in the following call(s) of this method.

source

fn end(self) -> Result<Self::Value, Self::Error>

Called when decoding has ended or there are no more bytes.

The decoder must validate the bytes passed in so far if it didn’t do so yet and return the decoded value or an error if the bytes were invalid.

Errors

This returns an error if the bytes passed so far are invalid as defined by the decoder. This commonly happens if the byte stream ended unexpectedly.

Provided Methods§

source

fn bytes_received(&mut self, bytes: &[u8]) -> Result<usize, Self::Error>

Processes nex chunk of bytes without updating the cursor.

This method is usually more convenient for the top-level callers which are receiving bytes from buffered readers. Instead of modifying the slice this returns the number of bytes consumed which can be passed to the consume method of a buffered reader.

source

fn then<R: Decoder, F: FnOnce(Self::Value) -> R>( self, fun: F ) -> Then<Self, R, F>

Chains another decoder after this one finishes such that the value of this one is used to initialize the next one.

source

fn then_try<E, R: Decoder, F: FnOnce(Self::Value) -> Result<R, E>>( self, fun: F ) -> ThenTry<E, Self, R, F>
where E: From<Self::Error> + From<R::Error>,

Chains another decoder after this one finishes such that the value of this one is used to initialize the next one.

Unlike then this combinator may also return an error and convert the errors into a custom one.

source

fn chain<D: Decoder>(self, following: D) -> Chain<Self, D>

Chains another decoder after this one to decode two values.

source

fn take(&mut self) -> Result<Self::Value, Self::Error>
where Self: Default,

Resets the decoder returning the decoded value.

source

fn sub_decode<E, F: FnMut(Self::Error) -> E>( &mut self, bytes: &mut &[u8], map_err: F ) -> ControlFlow<Result<(), E>, Self::Value>
where Self: Default,

Decodes a value from lower-level decoder.

When multiple decoders are chained one after another in a large state machine this method can simplify delegation of decoding to the underlying decoder. You can wrap decoding in a closure passed to Self::wrap_sub_decode and then just call sub_decode()? at the beginning of each decoding state and continue working with the returned value.

The method also accepts a function (closure) to convert the errors since using map_err would be annoying because of double wrapping. In case no conversion is desired simply pass in core::convert::identity.

Note that this requires the Default trait because it resets the decoder every time a value is decoded. Apart from this resolving borrowing issues it also allows easily decoding a stream of value in a loop. If you need to work with decoders that require a value (e.g. VecDecoder) it is recommended to create a specialized decoder that will decode both (e.g. using Then) and call sub_deode on that.

You may notice this looks a lot like await and in principle it is very similar. The differences are:

  • await also implements the state machine using Future trait. This doesn’t. The Future::poll method would have to have another argument for us to be able to use it.
  • This returns ControlFlow instead of Poll<Result> to make it return in case of “not ready” as well. The Try implementation on Poll only returns on Err, never on Pending. This is important for ergonomics.
  • While it could be argued the type is morally Poll<Error> this one doesn’t implement Try either so it’s unsuitable for the purpose.
source

fn wrap_sub_decode<F: FnOnce() -> ControlFlow<Result<(), Self::Error>, Infallible>>( f: F ) -> Result<(), Self::Error>

Helper for using sub_decode.

This can be used together with sub_decode on sub-decoders to make decoding easier. It helps with type inference and converts ControlFlow into Result.

Note that this doesn’t allow returning ControlFlow::Continue as that wouldn’t make sense. It is recommended to just return ControlFlow::Break with the result returned from decode_chunk of the last decoder.

Object Safety§

This trait is not object safe.

Implementors§

source§

impl Decoder for ByteVecDecoder

Available on crate feature alloc only.
source§

impl Decoder for U8Decoder

source§

impl Decoder for Utf8StringDecoder

Available on crate feature alloc only.
source§

impl<E, First: Decoder, Second: Decoder, Fun: FnOnce(First::Value) -> Result<Second, E>> Decoder for ThenTry<E, First, Second, Fun>
where E: From<First::Error> + From<Second::Error>,

§

type Value = <Second as Decoder>::Value

§

type Error = E

source§

impl<First: Decoder, Second: Decoder> Decoder for Chain<First, Second>

§

type Value = (<First as Decoder>::Value, <Second as Decoder>::Value)

§

type Error = Either<<First as Decoder>::Error, <Second as Decoder>::Error>

source§

impl<First: Decoder, Second: Decoder, Fun: FnOnce(First::Value) -> Second> Decoder for Then<First, Second, Fun>

§

type Value = <Second as Decoder>::Value

§

type Error = Either<<First as Decoder>::Error, <Second as Decoder>::Error>

source§

impl<T: Int> Decoder for IntDecoder<T, BigEndian>

source§

impl<T: Int> Decoder for IntDecoder<T, LittleEndian>

source§

impl<const N: usize> Decoder for ByteArrayDecoder<N>

§

type Value = [u8; N]

§

type Error = UnexpectedEnd