hap_tlv8/lib.rs
1//! HomeKit Accessory Protocol (HAP) TLV8 encoding and decoding.
2//!
3//! This is Milestone 1 of the `hap-rust` roadmap. Every later milestone
4//! (`hap-crypto`, `hap-transport`, …) depends on the types defined here:
5//! the pairing exchange messages are TLV8.
6//!
7//! # The format
8//!
9//! A TLV8 stream is a sequence of items, each `(type: u8, length: u8, value)`.
10//! Two rules make it more than a trivial format:
11//!
12//! - **Fragmentation.** A value longer than 255 bytes is split across
13//! consecutive items of the *same* type; the reader concatenates them.
14//! [`Tlv8Writer::push`] fragments automatically; [`Tlv8Reader::parse`]
15//! reassembles.
16//! - **Separators.** A zero-length item of type [`SEPARATOR`] (`0xFF`)
17//! delimits repeated structures.
18//!
19//! Integers are encoded little-endian at a fixed width per field
20//! ([`Tlv8Writer::push_u8`] → 1 byte, [`Tlv8Writer::push_u16`] → 2 bytes, and
21//! so on); there is no minimal-width trimming, because HAP integer
22//! characteristics declare their width.
23//!
24//! # Fragmentation
25//!
26//! A logical value longer than 255 bytes is encoded as consecutive items of
27//! the same type. Because a full 255-byte item means "more follows", a value
28//! whose length is a non-zero exact multiple of 255 is terminated by a
29//! zero-length item of the same type. For example, a 256-byte value of type
30//! `0x09` encodes as `[0x09, 0xFF, <255 bytes>, 0x09, 0x01, <1 byte>]`, and a
31//! 255-byte value as `[0x09, 0xFF, <255 bytes>, 0x09, 0x00]`. The reader
32//! reverses this transparently.
33//!
34//! # Usage
35//!
36//! ```
37//! use hap_tlv8::{Tlv8Writer, Tlv8Reader};
38//!
39//! let mut bytes = Vec::new();
40//! let mut w = Tlv8Writer::new(&mut bytes);
41//! w.push(0x01, &[0xAB, 0xCD]);
42//! assert_eq!(bytes, [0x01, 0x02, 0xAB, 0xCD]);
43//!
44//! let items = Tlv8Reader::parse(&bytes).unwrap();
45//! assert_eq!(items, vec![(0x01, vec![0xAB, 0xCD])]);
46//! ```
47//!
48//! The doc-test uses `unwrap()`; real library code must propagate the
49//! [`Result`] instead.
50
51#![forbid(unsafe_code)]
52
53mod error;
54mod map;
55mod reader;
56mod writer;
57
58pub use error::{Result, Tlv8Error};
59pub use map::Tlv8Map;
60pub use reader::Tlv8Reader;
61pub use writer::Tlv8Writer;
62
63/// TLV8 separator type (`kTLVType_Separator`). A zero-length item of this
64/// type delimits repeated structures, such as a list of pairings.
65pub const SEPARATOR: u8 = 0xFF;