1use bytes::{Buf, BufMut};
9
10use crate::error::TwineTlvError;
11
12macro_rules! encoded_len {
13 ($len:expr) => {{
14 let len = $len;
15 if len < 0xFF {
16 len + 2 } else {
18 len + 4 }
20 }};
21}
22
23pub trait PutTlvLength: BufMut {
24 fn put_tlv_length(&mut self, length: usize);
25}
26
27impl PutTlvLength for &mut [u8] {
28 fn put_tlv_length(&mut self, length: usize) {
29 if length < 0xFF {
30 self.put_u8(length as u8);
31 } else {
32 self.put_u8(0xFF);
33 self.put_u16(length as u16);
34 }
35 }
36}
37
38pub trait GetTlvLength: Buf {
39 fn get_tlv_length(&mut self) -> usize;
43}
44
45impl GetTlvLength for &[u8] {
46 fn get_tlv_length(&mut self) -> usize {
47 let start_len = self.get_u8();
48
49 let extended_len = if start_len == 0xFF {
50 Some(self.get_u16())
51 } else {
52 None
53 };
54
55 let len = if let Some(len) = extended_len {
56 len
57 } else {
58 start_len as u16
59 };
60
61 len as usize
62 }
63}
64
65pub trait DecodeTlvUnchecked {
66 fn decode_tlv_unchecked(buffer: impl AsRef<[u8]>) -> Self
73 where
74 Self: Sized;
75}
76
77pub trait DecodeTlvValueUnchecked {
78 fn decode_tlv_value_unchecked(buffer: impl AsRef<[u8]>) -> Self
85 where
86 Self: Sized;
87}
88
89impl DecodeTlvValueUnchecked for u8 {
90 fn decode_tlv_value_unchecked(buffer: impl AsRef<[u8]>) -> Self {
91 let mut buffer = buffer.as_ref();
92 buffer.get_u8()
93 }
94}
95
96impl DecodeTlvValueUnchecked for u16 {
97 fn decode_tlv_value_unchecked(buffer: impl AsRef<[u8]>) -> Self {
98 let mut buffer = buffer.as_ref();
99 buffer.get_u16()
100 }
101}
102
103impl DecodeTlvValueUnchecked for u32 {
104 fn decode_tlv_value_unchecked(buffer: impl AsRef<[u8]>) -> Self {
105 let mut buffer = buffer.as_ref();
106 buffer.get_u32()
107 }
108}
109
110impl DecodeTlvValueUnchecked for u64 {
111 fn decode_tlv_value_unchecked(buffer: impl AsRef<[u8]>) -> Self {
112 let mut buffer = buffer.as_ref();
113 buffer.get_u64()
114 }
115}
116
117impl<const N: usize> DecodeTlvValueUnchecked for [u8; N] {
118 fn decode_tlv_value_unchecked(buffer: impl AsRef<[u8]>) -> Self {
119 let mut buffer = buffer.as_ref();
120 let mut array = [0_u8; N];
121
122 let count = core::cmp::min(N, buffer.len());
123 for slot in array.iter_mut().take(count) {
124 *slot = buffer.get_u8();
125 }
126 array
127 }
128}
129
130pub trait TryEncodeTlv: TryEncodeTlvValue {
131 fn try_encode_tlv(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError>;
135}
136
137pub trait TryEncodeTlvValue {
138 fn try_encode_tlv_value(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError>;
142}
143
144impl TryEncodeTlvValue for u8 {
145 fn try_encode_tlv_value(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError> {
146 let mut buffer = buffer;
147 buffer.put_u8(*self);
148 Ok(1)
149 }
150}
151
152impl TryEncodeTlvValue for u16 {
153 fn try_encode_tlv_value(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError> {
154 let mut buffer = buffer;
155 buffer.put_u16(*self);
156 Ok(2)
157 }
158}
159
160impl TryEncodeTlvValue for u32 {
161 fn try_encode_tlv_value(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError> {
162 let mut buffer = buffer;
163 buffer.put_u32(*self);
164 Ok(4)
165 }
166}
167
168impl TryEncodeTlvValue for u64 {
169 fn try_encode_tlv_value(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError> {
170 let mut buffer = buffer;
171 buffer.put_u64(*self);
172 Ok(8)
173 }
174}
175
176impl<const N: usize> TryEncodeTlvValue for [u8; N] {
177 fn try_encode_tlv_value(&self, buffer: &mut [u8]) -> Result<usize, TwineTlvError> {
178 let mut buffer = buffer;
179
180 if buffer.len() < N {
181 return Err(TwineTlvError::BufferEncodeTooShort);
182 }
183
184 for &byte in self.iter() {
185 buffer.put_u8(byte);
186 }
187
188 Ok(N)
189 }
190}
191
192pub trait TlvType {
193 const TLV_TYPE: u8;
195}
196
197pub trait TlvLength {
198 fn tlv_len(&self) -> usize;
200
201 fn tlv_len_is_constant() -> bool {
203 false
204 }
205
206 fn tlv_total_len(&self) -> usize {
208 encoded_len!(self.tlv_len())
209 }
210}
211
212pub trait TlvMetadata: TlvType + TlvLength {}
214
215pub trait TlvConstantMetadata: TlvMetadata {
217 const TLV_LEN: usize;
219
220 fn tlv_total_constant_len() -> usize {
222 encoded_len!(Self::TLV_LEN)
223 }
224}