Skip to main content

rs_matter/tlv/traits/
vec.rs

1/*
2 *
3 *    Copyright (c) 2024-2026 Project CHIP Authors
4 *
5 *    Licensed under the Apache License, Version 2.0 (the "License");
6 *    you may not use this file except in compliance with the License.
7 *    You may obtain a copy of the License at
8 *
9 *        http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *    Unless required by applicable law or agreed to in writing, software
12 *    distributed under the License is distributed on an "AS IS" BASIS,
13 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *    See the License for the specific language governing permissions and
15 *    limitations under the License.
16 */
17
18//! TLV support for the `Vec<T, N>` type.
19//! `Vec<T, N>` is serialized and deserialized as a TLV array.
20//!
21//! Unlike Rust `[T; N]` arrays, the `Vec` type can be efficiently deserialized in-place, so use it
22//! when the array holds large structures (like fabrics, certificates, sessions and so on).
23//!
24//! Of course, the `Vec` type is always owned (even if the deserialized elements `T` do borrow from the
25//! deserializer), so it might consume more memory than necessary, as its memory is statically allocated
26//! to be N * size_of(T) bytes.
27//!
28//! For cases where the array does not need to be owned and instantiating `T` elements on the fly when
29//! traversing the array is tolerable (i.e. `T` is small enough), prefer `TLVArray`, which operates
30//! directly on the borrowed, encoded TLV representation of the whole array.
31
32use crate::error::{Error, ErrorCode};
33use crate::utils::init::{self, IntoFallibleInit};
34use crate::utils::storage::Vec;
35
36use super::{slice::tlv_array_iter, FromTLV, TLVArray, TLVElement, TLVTag, TLVWrite, ToTLV, TLV};
37
38impl<'a, T, const N: usize> FromTLV<'a> for Vec<T, N>
39where
40    T: FromTLV<'a> + 'a,
41{
42    fn from_tlv(element: &TLVElement<'a>) -> Result<Self, Error> {
43        let mut vec = Vec::<T, N>::new();
44
45        for item in TLVArray::new(element.clone())? {
46            vec.push(item?).map_err(|_| ErrorCode::ConstraintError)?;
47        }
48
49        Ok(vec)
50    }
51
52    fn init_from_tlv(tlv: TLVElement<'a>) -> impl init::Init<Self, Error> {
53        init::Init::chain(Vec::<T, N>::init().into_fallible(), move |vec| {
54            let mut iter = TLVArray::new(tlv)?.iter();
55
56            while let Some(item) = iter.try_next_init() {
57                vec.push_init(item?, || ErrorCode::ConstraintError.into())?;
58            }
59
60            Ok(())
61        })
62    }
63}
64
65impl<T, const N: usize> ToTLV for Vec<T, N>
66where
67    T: ToTLV,
68{
69    fn to_tlv<W: TLVWrite>(&self, tag: &TLVTag, tw: W) -> Result<(), Error> {
70        self.as_slice().to_tlv(tag, tw)
71    }
72
73    fn tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
74        tlv_array_iter(tag, self.iter())
75    }
76}
77
78/// TLV support for the heap-allocated `alloc::vec::Vec<T>` (unbounded, no `N`).
79/// Serialized/deserialized as a TLV array, like the bounded `Vec<T, N>` above.
80#[cfg(feature = "alloc")]
81impl<'a, T> FromTLV<'a> for alloc::vec::Vec<T>
82where
83    T: FromTLV<'a> + 'a,
84{
85    fn from_tlv(element: &TLVElement<'a>) -> Result<Self, Error> {
86        let mut vec = alloc::vec::Vec::new();
87
88        for item in TLVArray::new(element.clone())? {
89            vec.push(item?);
90        }
91
92        Ok(vec)
93    }
94}
95
96#[cfg(feature = "alloc")]
97impl<T> ToTLV for alloc::vec::Vec<T>
98where
99    T: ToTLV,
100{
101    fn to_tlv<W: TLVWrite>(&self, tag: &TLVTag, tw: W) -> Result<(), Error> {
102        self.as_slice().to_tlv(tag, tw)
103    }
104
105    fn tlv_iter(&self, tag: TLVTag) -> impl Iterator<Item = Result<TLV<'_>, Error>> {
106        tlv_array_iter(tag, self.iter())
107    }
108}