Skip to main content

Crate tinyklv

Crate tinyklv 

Source
Expand description

§tinyklv - KLV framework in Rust

Crates.io Documentation License: MIT MSRV CI

A derive-macro framework for encoding and decoding Key-Length-Value (KLV) binary streams, built on winnow parser combinators.

§What is KLV?

KLV is a generic Tag-Length-Value (TLV) framing pattern: every field in a byte stream is prefixed by a key identifying it and a length giving its size. It is the backbone of telemetry packets, video metadata streams, IoT sensor framing, and most custom binary protocols that need to evolve without breaking older parsers.

tinyklv is protocol-agnostic. It ships no baked-in standards - you declare your keys, your length encoding, your sentinel, and the codec for each field via attributes on a struct. The derive macro generates the encoder/decoder trait implementations; you control the schema.

§Quick Start

cargo add tinyklv
use tinyklv::Klv;
use tinyklv::prelude::*;
use tinyklv::dec::binary as decb;
use tinyklv::enc::binary as encb;

#[derive(Klv, Debug, PartialEq)]
#[klv(
    stream = &[u8],
    sentinel = b"\x47\x48",
    key(dec = decb::u8, enc = encb::u8),
    len(dec = decb::u8_as_usize,
        enc = encb::u8_from_usize),
)]
struct Heartbeat {
    #[klv(
        key = 0x01,
        dec = decb::u8,
        enc = *encb::u8,
    )]
    sequence: u8,

    #[klv(
        key = 0x02,
        dec = decb::be_u16,
        enc = *encb::be_u16,
    )]
    temperature_centideg: u16,
}

fn main() {
    let original = Heartbeat {
        sequence: 42,
        temperature_centideg: 2350,
    };
    let frame = original.encode_frame();
    let decoded = Heartbeat::decode_frame(
        &mut frame.as_slice()
    ).unwrap();
    assert_eq!(decoded, original);
}

Full annotated version: examples/01_hello_world.rs.

§Feature Highlights

  • #[derive(Klv)] generates encode and decode in one pass
  • Built-in codecs: binary (native/BE/LE for u8..u128, i8..i128, f32/f64), BER length, BER-OID keys, UTF-8 / UTF-16 / ASCII strings
  • Sentinel seeking - resync on noisy byte streams
  • Streaming partial packets - ::decoder(), iter(), next(), and DecodePartial
  • Repeated decode with user-defined break conditions
  • Nested Klv structs - compose packets from sub-packets
  • Generic structs and lifetimes supported
  • Option<T> fields, per-field and per-container defaults, trait_fallback, deny_unknown_keys
  • Stream type is user-selected - any winnow::Stream works

§Traits

TraitPurposeDerived?
DecodeValue<S>Decode value body from an unframed sliceyes
DecodeFrame<S>Seek sentinel, read length, subslice, then decodeyes
EncodeValue<O>Encode the value body (KLV triples, no frame header)yes
EncodeFrame<O>Encode sentinel + length + value bodyyes
DrainFrames<S>Decode a sentinel-framed stream into Vec<T>yes
DecodePartial<S>Streaming-aware decode returning Packet<T, P>yes
Decoder<P, S>Owned-buffer streaming decoder with feed, iter, and nextyes
BreakCondition<S>Per-(key, len) stop predicate for decode loopsno

§Documentation

§Contributing

Issues and pull requests welcome at https://github.com/arpadav/tinyklv. Run cargo test --all and cargo clippy --all-targets -- -D warnings before opening a PR.

§License

Licensed under the MIT License. See LICENSE for details.

§Support

If tinyklv is useful to you:

  • Buy Me a Coffee
  • Bitcoin: bc1q5stdywthj254agv80s5gky6440xy73cpqgv0q7 Author: aav

Re-exports§

pub use decoder::Decoder;
pub use decoder::Packet;
pub use codecs::*;
pub use traits::*;

Modules§

codecs
Codec Naming Conventions
decoder
Streaming KLV decoder
prelude
Convenience re-export of all traits and parser primitives needed to work with KLV streams
traits
Trait Architecture

Macros§

cast
Sets precision of a parsed value
cast_enc
Encode counterpart of cast!. Casts to data type, then encodes.
scale
Scales a parsed value of some predefined precision
scale_enc
Encode counterpart of scale!. Divides by scale factor, casts to data type, then encodes.
scale_offset_enc
Encode counterpart of scale! with offset. Subtracts offset, divides by scale, casts to data type, then encodes.

Type Aliases§

Result
Convenience re-export of winnow::Result

Derive Macros§

Klv
tinyklv proc-macro