Skip to main content

matter_codec/
value.rs

1//! Matter TLV element values.
2//!
3//! Phase 3 of `matter-codec` adds container variants. The full TLV value
4//! space is now represented.
5
6use crate::tag::Tag;
7
8/// A decoded Matter TLV value, collapsed across wire widths.
9///
10/// Integer widths and float widths are erased from the public type — the
11/// encoder chooses the minimal wire width per the spec, and the decoder
12/// produces the same Rust type regardless of the width the bytes used. If
13/// you need exact-byte round-trip for non-minimal inputs, use the reader's
14/// span APIs ([`crate::TlvReader::element_span`] /
15/// [`crate::TlvReader::skip_container_span`] + [`crate::TlvReader::span_bytes`]),
16/// which expose an element's raw bytes for width-preserving re-emission.
17#[derive(Debug, Clone, PartialEq)]
18#[non_exhaustive]
19pub enum Value {
20    /// A boolean.
21    Bool(bool),
22
23    /// An unsigned integer, encoded on the wire in 1, 2, 4, or 8 bytes
24    /// (minimal width).
25    Uint(u64),
26
27    /// A signed integer, encoded on the wire in 1, 2, 4, or 8 bytes
28    /// (minimal width).
29    Int(i64),
30
31    /// A 4-byte IEEE 754 single-precision float.
32    Float(f32),
33
34    /// An 8-byte IEEE 754 double-precision float.
35    Double(f64),
36
37    /// A UTF-8 string. The wire format is a 1/2/4/8-byte little-endian
38    /// length field (writer picks the minimal width) followed by the
39    /// raw UTF-8 bytes. The reader rejects invalid UTF-8 with
40    /// [`crate::Error::InvalidUtf8`].
41    Utf8(String),
42
43    /// An octet string. The wire format is a 1/2/4/8-byte little-endian
44    /// length field (writer picks the minimal width) followed by the
45    /// raw bytes.
46    Bytes(Vec<u8>),
47
48    /// A structure. Each member carries its own tag; members are
49    /// typically context-tagged but the spec permits any non-anonymous
50    /// form.
51    Structure(Vec<(Tag, Value)>),
52
53    /// An array. Elements share a single type; the spec requires every
54    /// element to carry an anonymous tag, which the reader enforces and
55    /// the writer always emits.
56    Array(Vec<Value>),
57
58    /// A list. Members may carry any tag form (including anonymous), and
59    /// member types are not required to be uniform.
60    List(Vec<(Tag, Value)>),
61
62    /// The TLV null value (element type `0x14`).
63    Null,
64}
65
66/// A borrowed view of one decoded scalar TLV value — the zero-copy sibling
67/// of [`Value`]. Strings and byte strings borrow directly from the reader's
68/// input; scalars are carried by value. Containers never appear here: the
69/// streaming [`crate::TlvReader::next_ref`] API reports them as
70/// `ContainerStart`/`ContainerEnd` events, so no owned children are built.
71///
72/// `Utf8` carries the same IS1-truncated text the owned path presents (the
73/// text before the first `0x1F` localized-string separator); access to the
74/// raw suffix (LSID) remains a separate additive follow-up.
75#[derive(Debug, Clone, Copy, PartialEq)]
76#[non_exhaustive]
77pub enum ValueRef<'a> {
78    /// A boolean.
79    Bool(bool),
80    /// An unsigned integer (any wire width).
81    Uint(u64),
82    /// A signed integer (any wire width).
83    Int(i64),
84    /// A 4-byte IEEE 754 single-precision float.
85    Float(f32),
86    /// An 8-byte IEEE 754 double-precision float.
87    Double(f64),
88    /// A UTF-8 string borrowing the reader's input (IS1-truncated text).
89    Utf8(&'a str),
90    /// An octet string borrowing the reader's input.
91    Bytes(&'a [u8]),
92    /// The TLV null value.
93    Null,
94}
95
96impl From<ValueRef<'_>> for Value {
97    // Called once per materialised element by the reader's tree builder (and
98    // by every cross-crate `next()` caller through `Element::from`), so it is
99    // inlined: the discriminant match then folds into the caller's own match
100    // and only the string/bytes arms keep their allocation.
101    #[inline]
102    fn from(v: ValueRef<'_>) -> Self {
103        match v {
104            ValueRef::Bool(b) => Value::Bool(b),
105            ValueRef::Uint(n) => Value::Uint(n),
106            ValueRef::Int(n) => Value::Int(n),
107            ValueRef::Float(f) => Value::Float(f),
108            ValueRef::Double(f) => Value::Double(f),
109            ValueRef::Utf8(s) => Value::Utf8(String::from(s)),
110            ValueRef::Bytes(b) => Value::Bytes(b.to_vec()),
111            ValueRef::Null => Value::Null,
112        }
113    }
114}