1pub trait Length {
32 fn length(&self) -> usize;
33}
34
35pub trait Encode: Length {
84 fn encode(&self, dst: &mut [u8]) -> usize;
88}
89
90pub(crate) trait EncodeExt: Encode {
91 fn encode_move(&self, dst: &mut [u8], size: usize) -> usize {
92 size + self.encode(&mut dst[size..])
93 }
94}
95
96impl<T: Encode> EncodeExt for T {}
97
98impl<T: Length> Length for Option<T> {
99 fn length(&self) -> usize {
100 self.as_ref().map(Length::length).unwrap_or(0)
101 }
102}
103
104impl<T: Length> Length for alloc::vec::Vec<T> {
105 fn length(&self) -> usize {
106 self.iter().map(Length::length).sum()
107 }
108}
109
110impl<T: Encode> Encode for Option<T> {
111 fn encode(&self, dst: &mut [u8]) -> usize {
112 self.as_ref().map(|item| item.encode(dst)).unwrap_or(0)
113 }
114}
115
116impl<T: Encode> Encode for alloc::vec::Vec<T> {
117 fn encode(&self, dst: &mut [u8]) -> usize {
118 self.iter()
119 .fold(0, |acc, item| acc + item.encode(&mut dst[acc..]))
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use crate::types::{AnyOctetString, COctetString, EmptyOrFullCOctetString, OctetString};
126
127 use super::*;
128
129 #[test]
130 fn length_option() {
131 let value: Option<u8> = Some(0u8);
132 assert_eq!(value.length(), 1);
133
134 let value: Option<u8> = None;
135 assert_eq!(value.length(), 0);
136 }
137
138 #[test]
139 fn length_vec() {
140 let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
141 assert_eq!(values.length(), 10);
142
143 let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
144 assert_eq!(values.length(), 20);
145
146 let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
147 assert_eq!(values.length(), 40);
148
149 let values = alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
150 assert_eq!(values.length(), 10);
151
152 let values = alloc::vec![
153 COctetString::<1, 6>::new(b"Hello\0").unwrap(),
154 COctetString::<1, 6>::new(b"World\0").unwrap(),
155 ];
156 assert_eq!(values.length(), 12);
157
158 let values = alloc::vec![
159 EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
160 EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
161 ];
162 assert_eq!(values.length(), 12);
163
164 let values = alloc::vec![
165 OctetString::<0, 5>::new(b"Hello").unwrap(),
166 OctetString::<0, 5>::new(b"World").unwrap(),
167 ];
168 assert_eq!(values.length(), 10);
169 }
170
171 #[test]
172 fn encode_option() {
173 let buf = &mut [0u8; 1024];
174
175 let value: Option<u8> = Some(0u8);
176 assert!(buf.len() >= value.length());
177
178 let size = value.encode(buf);
179
180 assert_eq!(size, 1);
181 assert_eq!(&buf[..size], &[0]);
182
183 let value: Option<u8> = None;
184 assert!(buf.len() >= value.length());
185
186 let size = value.encode(buf);
187
188 assert_eq!(size, 0);
189 }
190
191 #[test]
192 fn encode_vec() {
193 let buf = &mut [0u8; 1024];
194
195 let values: alloc::vec::Vec<u8> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
196 assert!(buf.len() >= values.length());
197
198 let size = values.encode(buf);
199
200 assert_eq!(size, 10);
201 assert_eq!(&buf[..size], &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
202
203 let values: alloc::vec::Vec<u16> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
204 assert!(buf.len() >= values.length());
205
206 let size = values.encode(buf);
207
208 assert_eq!(size, 20);
209 assert_eq!(
210 &buf[..size],
211 &[0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9]
212 );
213
214 let values: alloc::vec::Vec<u32> = alloc::vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
215 assert!(buf.len() >= values.length());
216
217 let size = values.encode(buf);
218 assert_eq!(size, 40);
219
220 assert_eq!(
221 &buf[..size],
222 &[
223 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 5, 0, 0, 0, 6,
224 0, 0, 0, 7, 0, 0, 0, 8, 0, 0, 0, 9
225 ]
226 );
227
228 let values = alloc::vec![AnyOctetString::new(b"Hello"), AnyOctetString::new(b"World")];
229 assert!(buf.len() >= values.length());
230
231 let size = values.encode(buf);
232
233 assert_eq!(size, 10);
234 assert_eq!(&buf[..size], b"HelloWorld");
235
236 let values = alloc::vec![
237 COctetString::<1, 6>::new(b"Hello\0").unwrap(),
238 COctetString::<1, 6>::new(b"World\0").unwrap(),
239 ];
240 assert!(buf.len() >= values.length());
241
242 let size = values.encode(buf);
243
244 assert_eq!(size, 12);
245 assert_eq!(&buf[..size], b"Hello\0World\0");
246
247 let values = alloc::vec![
248 EmptyOrFullCOctetString::<6>::new(b"Hello\0").unwrap(),
249 EmptyOrFullCOctetString::<6>::new(b"World\0").unwrap(),
250 ];
251 assert!(buf.len() >= values.length());
252
253 let size = values.encode(buf);
254
255 assert_eq!(size, 12);
256 assert_eq!(&buf[..size], b"Hello\0World\0");
257
258 let values = alloc::vec![
259 OctetString::<0, 5>::new(b"Hello").unwrap(),
260 OctetString::<0, 5>::new(b"World").unwrap(),
261 ];
262 assert!(buf.len() >= values.length());
263
264 let size = values.encode(buf);
265
266 assert_eq!(size, 10);
267 assert_eq!(&buf[..size], b"HelloWorld");
268 }
269}