Skip to main content

Decoder

Struct Decoder 

Source
pub struct Decoder<P, S> { /* private fields */ }
Expand description

Owned-buffer streaming decoder, parameterised on the Partial type.

Accepts bytes via feed and yields decoded values via next. A None from next means “need more bytes, call feed again” - malformed packets are silently skipped (the framed bytes are drained to guarantee forward progress).

§Example

// fresh mode (no in-flight partial): seek sentinel + decode framed body
let mut dec = Decoder::<<MyPacket as DecodePartial<&[u8]>>::Partial>::new();
let mut scratch = [0u8; 2048];
loop {
    let n = socket.recv(&mut scratch)?;
    dec.feed(&scratch[..n]);
    while let Some(pkt) = dec.next() {
        handle(pkt);
    }
}

// resume mode: handed back from `Packet::NeedMore`
match MyPacket::decode_partial(&mut input) {
    Ok(Packet::Ready(t)) => use_packet(t),
    Ok(Packet::NeedMore(partial)) => {
        let mut dec = Decoder::new();
        dec.feed(more_bytes);
        while let Some(pkt) = dec.next() {
            use_packet(pkt);
            break;
        }
    }
    Err(label) => report(label),
}

Implementations§

Source§

impl<P, S> Decoder<P, S>

Decoder implementation

Source

pub fn new() -> Self

Constructs an empty Decoder in fresh mode with no buffered bytes and no in-flight partial

Fresh mode means the decoder will seek a sentinel boundary on the next Self::next call. Use Self::with_capacity when the expected packet size is known in advance, to avoid reallocations.

§Example
use tinyklv::Decoder;

// type inference requires the partial type to be known from context
// let mut dec: Decoder<MyPacketPartial, &[u8]> = Decoder::new();
Source

pub fn with_capacity(cap: usize) -> Self

Constructs an empty Decoder in fresh mode with a pre-allocated internal buffer

Equivalent to Self::new but avoids the first reallocation when the caller knows roughly how many bytes will arrive. The cap hint is passed to Vec::with_capacity; the buffer will still grow beyond cap if needed.

§Arguments
  • cap - Initial byte capacity to pre-allocate in the internal buffer
Source

pub fn buffered(&self) -> &[u8]

Returns the bytes currently buffered but not yet consumed by decoding

Useful for observability, diagnostics, and logging. The returned slice is borrowed from the decoder’s internal Vec<u8> and does not copy.

§Returns

A &[u8] view of the pending bytes; empty when all data has been decoded

Source

pub fn partial(&self) -> Option<&P>

Borrows the in-flight partial, if any

Returns Some(&P) only when the decoder is in resume mode - i.e., after a Packet::NeedMore result was stored and before the next Self::next call successfully completes the packet. Returns None when the decoder is in fresh mode.

§Returns

Some(&P) when a partial packet is in-flight, None in fresh mode

Source

pub fn into_partial(self) -> Option<P>

Consumes the decoder and returns the in-flight partial, if one exists

Used by the derive-generated decode_partial wrapper to convert a “buffer fully consumed with NeedMore still pending” state into a finalisation decision at the fresh-mode boundary. Callers outside of generated code rarely need this directly; prefer Self::finish on the &[u8] specialisation when the upstream signals end-of-stream.

§Returns

Some(P) if a partial is in-flight, None in fresh mode

Source

pub fn clear(&mut self)

Drops all buffered bytes and clears any in-flight partial, resetting the decoder to fresh mode

Call this after a crate::decoder::iter::DecodeIterError::Malformed error when you want a clean resync point rather than byte-walking through the corrupt region. After clear, the next Self::next call will seek a new sentinel from scratch.

Source

pub fn feed(&mut self, bytes: &[u8])

Appends bytes to the internal buffer without triggering decoding

This is the intake point for new data arriving from a socket, ring buffer, or any other byte source. Decoding is intentionally deferred: call Self::next or iterate with Self::iter after feeding to attempt to produce complete values from the accumulated bytes.

§Arguments
  • bytes - The new bytes to append; may be a partial packet, multiple packets, or anything in between
Source

pub fn iter(&mut self) -> DecoderIter<'_, P, S>

Returns a borrowing iterator that yields decoded values from the buffer

The returned DecoderIter borrows self mutably and yields T values (the Partial::Final type) until the buffer is exhausted or a packet is incomplete. Buffered-but-undecoded bytes are retained between iterations so that a later Self::feed + re-iteration can pick up where decoding stopped.

§Returns

A DecoderIter borrowing this decoder for the lifetime of the iterator

Source

pub fn next<T>(&mut self) -> Option<T>
where S: Stream, P: Partial<Final = T> + Default, Self: PartialIterator<P>,

Decodes and returns the next complete value from the buffer, if one is available

Calls Self::iter and pulls one item. Returns None when the buffer contains no complete packet (EOF, incomplete, or malformed). Malformed packets are silently skipped - the framed bytes are drained - to keep the decoder advancing. Call Self::buffered afterward to inspect remaining bytes.

§Returns

Some(T) when a complete, successfully-decoded value is available, None otherwise

Source§

impl<P, T> Decoder<P, &[u8]>
where P: Partial<Final = T> + Default, for<'a> T: DecodePartial<&'a [u8], Partial = P> + ResumePartial<&'a [u8]> + SeekSentinel<&'a [u8]>,

Decoder implementation specialised to &[u8] streams, adding Decoder::finish

This specialisation adds Decoder::finish, which is only meaningful on &[u8] streams where the end-of-stream condition is definite. When the decoder carries an in-flight partial, Decoder::next resumes DecodePartial::decode_partial without re-seeking the sentinel because the partial state already contains the bytes consumed past the framing.

Source

pub fn finish(self) -> Result<T, DecodeIterError>

Force-finalises the in-flight partial, consuming the decoder

Call this when the upstream transport signals end-of-stream and you want either the accumulated partial surfaced as T (if all required fields are present) or a definitive error. The decoder is consumed and the buffered bytes are discarded - no further decoding is possible after this call.

If no partial is in-flight, a default partial is finalised; depending on the T type this may succeed (all fields optional) or fail (required fields missing).

§Returns

Ok(T) when the partial can be finalised with all required fields satisfied, or Err(DecodeIterError::Malformed) when required fields are absent

Trait Implementations§

Source§

impl<P, S> Default for Decoder<P, S>

Decoder implementation of Default

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl<'d, P, T, S> IntoIterator for &'d mut Decoder<P, S>
where Decoder<P, S>: PartialIterator<P>, S: Stream, P: Partial<Final = T> + Default, for<'b> T: DecodePartial<S, Partial = P> + ResumePartial<S> + SeekSentinel<S>,

Decoder implementation of IntoIterator

Source§

type Item = T

The type of the elements being iterated over.
Source§

type IntoIter = DecoderIter<'d, P, S>

Which kind of iterator are we turning this into?
Source§

fn into_iter(self) -> Self::IntoIter

Creates an iterator from a value. Read more
Source§

impl<'a, P, T> PartialIterator<P> for &mut Decoder<P, &'a [u8]>
where P: Partial<Final = T> + Default, Decoder<P, &'a [u8]>: PartialIterator<P>,

&mut Decoder implementation of PartialIterator for [&[u8]]

Delegates both methods to the owned Decoder impl via double-deref so that a mutable reference to a decoder can be used anywhere an owned decoder is expected without moving it.

Source§

fn next_resume(&mut self) -> Result<<P as Partial>::Final, DecodeIterError>

Resume-mode entry
Source§

fn next_fresh(&mut self) -> Result<<P as Partial>::Final, DecodeIterError>

Fresh-mode entry Read more
Source§

impl<P, T> PartialIterator<P> for Decoder<P, &[u8]>
where P: Partial<Final = T> + Default, for<'a> T: DecodePartial<&'a [u8], Partial = P> + ResumePartial<&'a [u8]> + SeekSentinel<&'a [u8]>,

Decoder implementation of PartialIterator for [&[u8]]

Source§

fn next_resume(&mut self) -> Result<T, DecodeIterError>

Resumes decoding a packet that was previously interrupted with crate::decoder::Packet::NeedMore

Pops the in-flight partial from self.partial, runs [crate::traits::ResumePartial::resume_partial] against the buffered bytes, then drains the consumed prefix from the buffer regardless of outcome.

Returns Ok(T) when the packet is now complete, or one of:

Source§

fn next_fresh(&mut self) -> Result<T, DecodeIterError>

Seeks the next sentinel boundary and decodes the framed packet body

Runs crate::traits::SeekSentinel::seek_sentinel to locate and consume the packet framing (sentinel + length prefix), then calls crate::traits::DecodePartial::decode_partial on the framed body slice. The consumed bytes (framing + body) are drained from the buffer.

A NeedMore result from decode_partial inside fresh mode means the framing declared a body length that the parser did not fully consume, which is treated as malformed rather than resumable (the body was already framed to an exact length).

Returns Ok(T) when decoding succeeds, or one of:

Auto Trait Implementations§

§

impl<P, S> Freeze for Decoder<P, S>
where P: Freeze,

§

impl<P, S> RefUnwindSafe for Decoder<P, S>

§

impl<P, S> Send for Decoder<P, S>
where P: Send, S: Send,

§

impl<P, S> Sync for Decoder<P, S>
where P: Sync, S: Sync,

§

impl<P, S> Unpin for Decoder<P, S>
where P: Unpin, S: Unpin,

§

impl<P, S> UnsafeUnpin for Decoder<P, S>
where P: UnsafeUnpin,

§

impl<P, S> UnwindSafe for Decoder<P, S>
where P: UnwindSafe, S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.