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
impl<P, S> Decoder<P, S>
Decoder implementation
Sourcepub fn new() -> Self
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();Sourcepub fn with_capacity(cap: usize) -> Self
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
Sourcepub fn buffered(&self) -> &[u8] ⓘ
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
Sourcepub fn partial(&self) -> Option<&P>
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
Sourcepub fn into_partial(self) -> Option<P>
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
Sourcepub fn clear(&mut self)
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.
Sourcepub fn feed(&mut self, bytes: &[u8])
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
Sourcepub fn iter(&mut self) -> DecoderIter<'_, P, S> ⓘ
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
Sourcepub fn next<T>(&mut self) -> Option<T>
pub fn next<T>(&mut self) -> Option<T>
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
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.
Sourcepub fn finish(self) -> Result<T, DecodeIterError>
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<'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
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§impl<'a, P, T> PartialIterator<P> for &mut Decoder<P, &'a [u8]>
&mut Decoder implementation of PartialIterator for [&[u8]]
impl<'a, P, T> PartialIterator<P> for &mut Decoder<P, &'a [u8]>
&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>
fn next_resume(&mut self) -> Result<<P as Partial>::Final, DecodeIterError>
Source§fn next_fresh(&mut self) -> Result<<P as Partial>::Final, DecodeIterError>
fn next_fresh(&mut self) -> Result<<P as Partial>::Final, DecodeIterError>
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]]
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>
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:
DecodeIterError::Eof- buffer is empty and no partial is setDecodeIterError::NeedMore- the partial made progress but still needs more bytes; the updated partial is re-stored inself.partialDecodeIterError::Malformed- decoding failed; the consumed bytes are drained to advance the stream past the bad data
Source§fn next_fresh(&mut self) -> Result<T, DecodeIterError>
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:
DecodeIterError::Eof- buffer is emptyDecodeIterError::Malformed- sentinel seek or body decode failed