# Traits
`use tinyklv::prelude::*` brings every trait into scope so the method
calls work. This page documents the traits a user interacts with
directly.
## Decode traits
### `DecodeValue<S>`
```rust,ignore
pub trait DecodeValue<S>: Sized
where
S: winnow::stream::Stream,
{
fn decode_value(input: &mut S) -> crate::Result<Self>;
}
```
Parses a KLV triple stream until the container's field set is
satisfied (or the stream is exhausted, depending on
`deny_unknown_keys`). Generated by `#[derive(Klv)]` unless
`allow_unimplemented_decode` is set.
Types implementing `DecodeValue` also get
`Vec<T>::decode_value(&mut stream) -> Vec<T>` via a blanket impl for
unframed repeated decode. For sentinel-framed streams, use
`T::drain_frames(&mut stream)` instead (requires `DecodeFrame`). See
[Tutorial 13 - Repeated extraction](../tutorial/advanced/13-repeated-extraction.md).
### `DecodePartial<S>`
```rust,ignore
pub enum Packet<T, P>
where
P: Partial<Final = T>,
{
Ready(T),
NeedMore(P),
}
pub trait DecodePartial<S>: Sized
where
S: winnow::stream::Stream,
{
type Partial: Default + Partial<Final = Self>;
fn decode_partial(
input: &mut S,
) -> Result<Packet<Self, Self::Partial>, &'static str>;
}
```
Streaming-aware companion to `DecodeValue`. Returns a `Packet`
enum wrapped in `Result`:
| `Ready(t)` | Full value decoded; cursor advanced past consumed bytes. |
| `NeedMore(p)` | Not enough bytes yet; partial `p` carries every field decoded so far. Cursor rewound to allow retry with more bytes. |
The outer `Result` carries a `&'static str` label on `Err` - not a
`ContextError`. `Err(label)` means unrecoverable parse failure; the
`Decoder` wraps the label into a `ContextError` with position info.
`DecodeValue` and `DecodePartial` are both generated by
`#[derive(Klv)]`. `DecodeValue` is a thin wrapper that delegates to
`DecodePartial` and maps `NeedMore` to a truncation `Err`, because the
one-shot contract assumes the caller has already committed all bytes.
Typical direct use is rare - most callers reach for `Decoder` instead
(see below). Direct use is valuable when you know the input is exactly
one complete packet's body and want to inspect the result explicitly.
At end-of-input, `decode_partial` still returns `NeedMore(p)` unless a
break condition ends the packet; if the caller knows the body is
complete, it should call `p.finalize()`.
### `Partial`
```rust,ignore
pub trait Partial: Sized {
type Final;
fn finalize(self) -> Result<Self::Final, &'static str>;
}
```
The in-flight parse state that can be finalised into a complete value.
`#[derive(Klv)]` generates a mirror struct (e.g. `MyPacketPartialPacket`)
where every KLV field becomes `Option<T>`. `finalize()` validates that
all required fields are populated and yields the final struct.
`TryFrom<Partial> for T` is also generated, so
`partial.try_into()` works without importing the `Partial` trait
directly.
### `ResumePartial<S>` (internal)
Re-entry point for resuming a paused decode from an existing partial.
Not typically called directly - `Decoder` and `DecodePartial` use it
internally. Advanced callers who manage their own partial lifecycle
can call `T::resume_partial(&mut input, partial)` to continue decoding
from a saved `NeedMore` state.
### `Decoder<P, S>`
```rust,ignore
pub struct Decoder<P, S> { /* owned Vec<u8> buffer + optional partial */ }
impl<P, S> Decoder<P, S> {
pub fn new() -> Self;
pub fn with_capacity(cap: usize) -> Self;
pub fn feed(&mut self, bytes: &[u8]);
pub fn buffered(&self) -> &[u8];
pub fn partial(&self) -> Option<&P>;
pub fn into_partial(self) -> Option<P>;
pub fn clear(&mut self);
pub fn iter(&mut self) -> DecoderIter<'_, P, S>;
pub fn next<T>(&mut self) -> Option<T>;
}
impl<P, T> Decoder<P, &[u8]>
where
P: Partial<Final = T> + Default,
{
pub fn finish(self) -> Result<T, DecodeIterError>;
}
```
User-facing buffered streaming API. Owns a byte buffer, accepts
incremental feeds from a socket / file / ring buffer, and yields
fully-decoded `T` values as enough bytes arrive.
Requires `T` to carry a `sentinel = ...` attribute - the decoder uses
the sentinel + declared packet length to locate each packet's
boundaries inside the buffer. Without that, there is no way to tell
one packet's bytes from the next inside a continuous stream.
Internally it has two modes:
- fresh mode: seek sentinel, read frame length, call `decode_partial` on the body
- resume mode: keep the in-flight partial and continue it with newly fed bytes
`next()` returns:
| `Some(t)` | Packet decoded; its framed bytes are drained from the internal buffer. |
| `None` | Need more bytes, a malformed packet was skipped, or no sentinel found yet. Call `feed` and retry. |
`finish(self) -> Result<T, DecodeIterError>` consumes the decoder and
force-finalises the in-flight partial. Use when the upstream signals
"no more bytes." `DecodeIterError` variants: `Eof`, `NeedMore`,
`Malformed(ContextError)`.
Typical usage:
```rust,ignore
let mut dec = Decoder::<MyPacketPartialPacket, &[u8]>::new();
let mut scratch = [0u8; 2048];
loop {
let n = socket.recv(&mut scratch)?;
dec.feed(&scratch[..n]);
for pkt in dec.iter() {
handle(pkt);
}
}
```
See [Tutorial 15 - Streaming partial packets](../tutorial/advanced/15-streaming-decode.md).
### `DecodeFrame<S>`
```rust,ignore
pub trait DecodeFrame<S>: Sized
where
S: winnow::stream::Stream,
{
fn decode_frame(input: &mut S) -> crate::Result<Self>;
}
```
Seeks the sentinel, reads the frame length, subslices the stream to
exactly that many bytes, and calls `decode_value` on the subslice.
`DecodeFrame` is a blanket impl over `SeekSentinel + DecodeValue`.
The derive does not generate it directly - it generates `SeekSentinel`
(which scans `input` for the sentinel, consumes sentinel + length, and
returns the body as a sub-slice), and the blanket impl provides
`decode_frame` for free. Only available when `sentinel = ...` is
declared.
## Encode traits
### `EncodeValue<O>`
```rust,ignore
pub trait EncodeValue<O: EncodedOutput> {
fn encode_value(&self) -> O;
}
```
Emits the KLV triples for this value (no sentinel, no frame length).
Generated by `#[derive(Klv)]` unless `allow_unimplemented_encode` is
set. `O` is typically `Vec<u8>`.
### `EncodeFrame<O>`
```rust,ignore
pub trait EncodeFrame<O: EncodedOutput> {
fn encode_frame(&self) -> O;
}
```
Emits a full packet: `sentinel + length + <encode_value output>`.
Only generated when the container declares `sentinel = ...`.
### `EncodeAs`
Controls how the `&` sigil routes a field reference to an encoder.
Documented in full at
[Sigil coercion & `EncodeAs`](./sigil-coercion.md).
## Control traits
### `BreakCondition<S>`
```rust,ignore
pub trait BreakCondition<S> {
fn break_condition<K, L>(
decoded_key: K,
decoded_len: L,
) -> BreakConditionType;
}
```
User-extensible stop predicate consulted inside the derive-generated
`decode_value` loop for each decoded `(key, len)`. A blanket impl
returning `Proceed` covers the common case. Override requires a manual
`DecodeValue` impl - the blanket impl wins over a derived one. See
[Tutorial 14 - Break conditions](../tutorial/advanced/14-break-condition.md).
`BreakConditionType` variants:
| `Proceed` | Run the normal decode step for this key (default) |
| `Skip` | Consume the value bytes, continue the loop |
| `Done` | Stop looping, return accumulated fields |
| `Abort(ContextError)` | Stop looping, return `Err` |