simple_tlv/traits.rs
1// pub use der::{Decodable, Encodable};
2//! Trait definitions
3
4use core::convert::{TryFrom, TryInto};
5use crate::{Decoder, Encoder, Error, header::Header, Length, Result, Tag, TaggedSlice, TaggedValue};
6
7#[cfg(feature = "alloc")]
8use {
9 alloc::vec::Vec,
10 core::iter,
11 crate::ErrorKind,
12};
13
14#[cfg(feature = "heapless")]
15use crate::ErrorKind;
16
17/// Decoding trait.
18///
19/// Decode out of decoder, which essentially is a slice of bytes.
20///
21/// One way to implement this trait is to implement `TryFrom<TaggedSlice<'_>, Error = Error>`.
22pub trait Decodable<'a>: Sized {
23 /// Attempt to decode this message using the provided decoder.
24 fn decode(decoder: &mut Decoder<'a>) -> Result<Self>;
25
26 /// Parse `Self` from the provided byte slice.
27 fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
28 let mut decoder = Decoder::new(bytes);
29 let result = Self::decode(&mut decoder)?;
30 decoder.finish(result)
31 }
32}
33
34impl<'a, T> Decodable<'a> for T
35where
36 T: TryFrom<TaggedSlice<'a>, Error = Error>,
37{
38 fn decode(decoder: &mut Decoder<'a>) -> Result<T> {
39 TaggedSlice::decode(decoder)
40 .and_then(Self::try_from)
41 .or_else(|e| decoder.error(e.kind()))
42 }
43}
44
45/// Encoding trait.
46///
47/// Encode into encoder, which essentially is a mutable slice of bytes.
48///
49/// Additionally, the encoded length needs to be known without actually encoding.
50pub trait Encodable {
51 /// Compute the length of this value in bytes when encoded as SIMPLE-TLV
52 fn encoded_length(&self) -> Result<Length>;
53
54 /// Encode this value as SIMPLE-TLV using the provided [`Encoder`].
55 fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()>;
56
57 /// Encode this value to the provided byte slice, returning a sub-slice
58 /// containing the encoded message.
59 fn encode_to_slice<'a>(&self, buf: &'a mut [u8]) -> Result<&'a [u8]> {
60 let mut encoder = Encoder::new(buf);
61 self.encode(&mut encoder)?;
62 Ok(encoder.finish()?)
63 }
64
65 /// Encode this message as SIMPLE-TLV, appending it to the provided
66 /// byte vector.
67 #[cfg(feature = "alloc")]
68 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
69 fn encode_to_vec(&self, buf: &mut Vec<u8>) -> Result<Length> {
70 let expected_len = self.encoded_length()?.to_usize();
71 let current_len = buf.len();
72 buf.reserve(expected_len);
73 buf.extend(iter::repeat(0).take(expected_len));
74
75 // TODO(nickray): seems the original in `der` is incorrect here?
76 // let mut encoder = Encoder::new(buf);
77 let mut encoder = Encoder::new(&mut buf[current_len..]);
78 self.encode(&mut encoder)?;
79 let actual_len = encoder.finish()?.len();
80
81 if expected_len != actual_len {
82 return Err(ErrorKind::Underlength {
83 expected: expected_len.try_into()?,
84 actual: actual_len.try_into()?,
85 }
86 .into());
87 }
88
89 actual_len.try_into()
90 }
91
92 /// Serialize this message as a byte vector.
93 #[cfg(feature = "alloc")]
94 #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
95 fn to_vec(&self) -> Result<Vec<u8>> {
96 let mut buf = Vec::new();
97 self.encode_to_vec(&mut buf)?;
98 Ok(buf)
99 }
100
101}
102
103#[cfg(feature = "heapless")]
104#[cfg_attr(docsrs, doc(cfg(feature = "heapless")))]
105/// The equivalent of the `encode_to_vec` and `to_vec` methods.
106///
107/// Separate trait because the generic parameter `N` would make `Encodable` not object safe.
108pub trait EncodableHeapless: Encodable {
109 /// Encode this message as SIMPLE-TLV, appending it to the provided
110 /// heapless byte vector.
111 fn encode_to_heapless_vec<N: heapless::ArrayLength<u8>>(&self, buf: &mut heapless::Vec<u8, N>) -> Result<Length> {
112 let expected_len = self.encoded_length()?.to_usize();
113 let current_len = buf.len();
114 // TODO(nickray): add a specific error for "Overcapacity" conditional on heapless feature?
115 buf.resize_default(current_len + expected_len).map_err(|_| Error::from(ErrorKind::Overlength))?;
116
117 let mut encoder = Encoder::new(&mut buf[current_len..]);
118 self.encode(&mut encoder)?;
119 let actual_len = encoder.finish()?.len();
120
121 if expected_len != actual_len {
122 return Err(ErrorKind::Underlength {
123 expected: expected_len.try_into()?,
124 actual: actual_len.try_into()?,
125 }
126 .into());
127 }
128
129 actual_len.try_into()
130 }
131
132 /// Serialize this message as a byte vector.
133 fn to_heapless_vec<N: heapless::ArrayLength<u8>>(&self) -> Result<heapless::Vec<u8, N>> {
134 let mut buf = heapless::Vec::new();
135 self.encode_to_heapless_vec(&mut buf)?;
136 Ok(buf)
137 }
138}
139
140/// Types that can be tagged.
141pub(crate) trait Taggable: Sized {
142 fn tagged(&self, tag: Tag) -> TaggedValue<&Self> {
143 TaggedValue::new(tag, self)
144 }
145}
146
147impl<X> Taggable for X where X: Sized {}
148
149// /// Types with an associated SIMPLE-TLV [`Tag`].
150// pub trait Tagged {
151// /// SIMPLE-TLV tag
152// const TAG: Tag;
153// }
154
155/// Types with an associated SIMPLE-TLV [`Tag`].
156///
157/// A tagged type implementing `Container` has a blanked implementation of `Encodable`.
158pub trait Tagged {
159 /// The tag
160 fn tag() -> Tag;
161}
162
163/// Multiple encodables in a container.
164///
165/// A container implementing `Tagged` has a blanked implementation of `Encodable`.
166pub trait Container {
167 /// Call the provided function with a slice of [`Encodable`] trait objects
168 /// representing the fields of this message.
169 ///
170 /// This method uses a callback because structs with fields which aren't
171 /// directly [`Encodable`] may need to construct temporary values from
172 /// their fields prior to encoding.
173 fn fields<F, T>(&self, f: F) -> Result<T>
174 where
175 F: FnOnce(&[&dyn Encodable]) -> Result<T>;
176}
177
178impl<TaggedContainer> Encodable for TaggedContainer
179where
180 TaggedContainer: Tagged + Container
181{
182 fn encoded_length(&self) -> Result<Length> {
183 #[allow(clippy::redundant_closure)]
184 // if we do as clippy tells, we get:
185 // 183 | let value_length = self.fields(Length::try_from)?;
186 // | ^^^^^^ one type is more general than the other
187 // |
188 // = note: expected type `FnOnce<(&[&dyn Encodable],)>`
189 // found type `FnOnce<(&[&dyn Encodable],)>`
190 let value_length = self.fields(|encodables| Length::try_from(encodables))?;
191 Header::new(Self::tag(), value_length)?.encoded_length() + value_length
192 }
193
194 fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
195 self.fields(|fields| encoder.encode_tagged_collection(Self::tag(), fields))
196 }
197}
198
199///// Multiple encodables, nested under a SIMPLE-TLV tag.
200/////
201///// This wraps up a common pattern for SIMPLE-TLV encoding.
202///// Implementations obtain a blanket `Encodable` implementation
203//pub trait TaggedContainer: Container + Tagged {}
204
205//pub trait Untagged {}
206
207///// Multiple encodables, side-by-side without a SIMPLE-TLV tag.
208/////
209///// This wraps up a common pattern for SIMPLE-TLV encoding.
210///// Implementations obtain a blanket `Encodable` implementation
211//pub trait UntaggedContainer: Container + Untagged {}
212
213// impl<UC> Encodable for UC
214// where
215// UC: Untagged + Container,
216// {
217// fn encoded_length(&self) -> Result<Length> {
218// todo!();
219// // let value_length = self.fields(|encodables| Length::try_from(encodables))?;
220// // Header::new(Self::tag(), value_length)?.encoded_length() + value_length
221// }
222
223// fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
224// todo!();
225// // self.fields(|fields| encoder.nested(Self::tag(), fields))
226// }
227// }
228
229// pub type UntaggedContainer<'a> = &'a [&'a dyn Encodable];
230
231// impl<'a> Encodable for UntaggedContainer<'a> {
232// fn encoded_length(&self) -> Result<Length> {
233// Length::try_from(*self)
234// }
235
236// fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
237// for encodable in self.iter() {
238// encodable.encode(encoder)?;
239// }
240// Ok(())
241// }
242// }
243
244impl<'a> Encodable for &'a [u8] {
245 fn encoded_length(&self) -> Result<Length> {
246 self.len().try_into()
247 }
248
249 /// Encode this value as SIMPLE-TLV using the provided [`Encoder`].
250 fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
251 encoder.bytes(self)
252 }
253}
254
255macro_rules! impl_array {
256 ($($N:literal),*) => {
257 $(
258 impl Encodable for [u8; $N] {
259 fn encoded_length(&self) -> Result<Length> {
260 Ok(($N as u8).into())
261 }
262
263 /// Encode this value as SIMPLE-TLV using the provided [`Encoder`].
264 fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
265 encoder.bytes(self.as_ref())
266 }
267 }
268
269 impl Decodable<'_> for [u8; $N] {
270 fn decode(decoder: &mut Decoder<'_>) -> Result<Self> {
271 use core::convert::TryInto;
272 let bytes: &[u8] = decoder.bytes($N as u8)?;
273 Ok(bytes.try_into().unwrap())
274 }
275 }
276 )*
277 }
278}
279
280impl_array!(
281 0,1,2,3,4,5,6,7,8,9,
282 10,11,12,13,14,15,16,17,18,19,
283 20,21,22,23,24,25,26,27,28,29,
284 30,31,32
285);
286
287#[cfg(test)]
288mod tests {
289
290 use core::convert::TryFrom;
291 use crate::{Decodable, Encodable, Error, Result, Tag, TaggedSlice};
292 use super::{Taggable, Tagged, Container};
293
294 // The types [u8; 2], [u8; 3], [u8; 4] stand in here for any types for the fields
295 // of a struct that are Decodable + Encodable. This means they can decode to/encode from
296 // a byte slice, but also that thye can declare their encoded length.
297 //
298 // The goal then is to tag the struct definition for a proc-macro that implements
299 // nested SIMPLE-TLV objects (as this is what we need in PIV return values)
300
301 // tag 0xAA
302 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
303 struct S {
304 // tag 0x11
305 x: [u8; 2],
306 // tag 0x22
307 y: [u8; 3],
308 // tag 0x33
309 z: [u8; 4],
310 }
311
312 // this is what needs to be done to get `Decodable`
313 impl<'a> TryFrom<TaggedSlice<'a>> for S {
314 type Error = Error;
315
316 fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<S> {
317 tagged_slice.tag().assert_eq(Tag::try_from(0xAA).unwrap())?;
318 tagged_slice.decode_nested(|decoder| {
319 let x = decoder.decode_tagged_value(Tag::try_from(0x11).unwrap())?;
320 let y = decoder.decode_tagged_value(Tag::try_from(0x22).unwrap())?;
321 let z = decoder.decode_tagged_value(Tag::try_from(0x33).unwrap())?;
322
323 Ok(Self { x, y, z })
324 })
325 }
326 }
327
328 // this is what needs to be done to get `Encodable`
329 impl Tagged for S {
330 fn tag() -> Tag {
331 Tag::try_from(0xAA).unwrap()
332 }
333 }
334
335 impl Container for S {
336 fn fields<F, T>(&self, field_encoder: F) -> Result<T>
337 where
338 F: FnOnce(&[&dyn Encodable]) -> Result<T>,
339 {
340 // both approaches equivalent
341 field_encoder(&[
342 &(Tag::try_from(0x11).unwrap().with_value(&self.x.as_ref())),
343 // &self.x.tagged(Tag::try_from(0x11).unwrap()),
344 &self.y.as_ref().tagged(Tag::try_from(0x22).unwrap()),
345 &self.z.as_ref().tagged(Tag::try_from(0x33).unwrap()),
346
347 ])
348 }
349 }
350
351 #[test]
352 fn reconstruct() {
353 let s = S { x: [1,2], y: [3,4,5], z: [6,7,8,9] };
354 let mut buf = [0u8; 1024];
355
356 let encoded = s.encode_to_slice(&mut buf).unwrap();
357
358 assert_eq!(encoded,
359 &[0xAA, 15,
360 0x11, 2, 1, 2,
361 0x22, 3, 3, 4, 5,
362 0x33, 4, 6, 7, 8, 9,
363 ],
364 );
365
366 let s2 = S::from_bytes(encoded).unwrap();
367
368 assert_eq!(s, s2);
369 }
370
371 // tag 0xBB
372 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
373 struct T {
374 // tag 0x01
375 s: S,
376 // tag 0x02
377 t: [u8; 3],
378 }
379
380 impl<'a> TryFrom<TaggedSlice<'a>> for T {
381 type Error = Error;
382
383 fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<Self> {
384 tagged_slice.tag().assert_eq(Tag::try_from(0xBB).unwrap())?;
385 tagged_slice.decode_nested(|decoder| {
386 let s = decoder.decode_tagged_value(Tag::try_from(0x01).unwrap())?;
387 let t = decoder.decode_tagged_value(Tag::try_from(0x02).unwrap())?;
388
389 Ok(Self { s, t })
390 })
391 }
392 }
393
394 impl Tagged for T {
395 fn tag() -> Tag {
396 Tag::try_from(0xBB).unwrap()
397 }
398 }
399
400 impl Container for T {
401 fn fields<F, Z>(&self, field_encoder: F) -> Result<Z>
402 where
403 F: FnOnce(&[&dyn Encodable]) -> Result<Z>,
404 {
405 field_encoder(&[
406 &self.s.tagged(Tag::try_from(0x1).unwrap()),
407 &self.t.as_ref().tagged(Tag::try_from(0x2).unwrap()),
408 ])
409 }
410 }
411
412
413 #[test]
414 fn nesty() {
415 let s = S { x: [1,2], y: [3,4,5], z: [6,7,8,9] };
416 let t = T { s, t: [0xA, 0xB, 0xC] };
417
418 let mut buf = [0u8; 1024];
419
420 let encoded = t.encode_to_slice(&mut buf).unwrap();
421
422 assert_eq!(encoded,
423 &[0xBB, 24,
424 0x1, 17,
425 0xAA, 15,
426 0x11, 2, 1, 2,
427 0x22, 3, 3, 4, 5,
428 0x33, 4, 6, 7, 8, 9,
429 0x2, 3,
430 0xA, 0xB, 0xC
431 ],
432 );
433
434 let t2 = T::from_bytes(encoded).unwrap();
435
436 assert_eq!(t, t2);
437 }
438
439 // tag 0xCC
440 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
441 struct T2 {
442 // no tag
443 s: S,
444 // tag 0x02
445 t: [u8; 3],
446 }
447
448 impl<'a> TryFrom<TaggedSlice<'a>> for T2 {
449 type Error = Error;
450
451 fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<Self> {
452 tagged_slice.tag().assert_eq(Tag::try_from(0xCC).unwrap())?;
453 tagged_slice.decode_nested(|decoder| {
454 let s = decoder.decode()?;
455 let t = decoder.decode_tagged_value(Tag::try_from(0x02).unwrap())?;
456
457 Ok(Self { s, t })
458 })
459 }
460 }
461
462 impl Tagged for T2 {
463 fn tag() -> Tag {
464 Tag::try_from(0xCC).unwrap()
465 }
466 }
467
468 impl Container for T2 {
469 fn fields<F, Z>(&self, field_encoder: F) -> Result<Z>
470 where
471 F: FnOnce(&[&dyn Encodable]) -> Result<Z>,
472 {
473 field_encoder(&[
474 &self.s,
475 &self.t.as_ref().tagged(Tag::try_from(0x2).unwrap()),
476 ])
477 }
478 }
479
480
481 #[test]
482 fn nesty2() {
483 let s = S { x: [1,2], y: [3,4,5], z: [6,7,8,9] };
484 let t = T2 { s, t: [0xA, 0xB, 0xC] };
485
486 let mut buf = [0u8; 1024];
487
488 let encoded = t.encode_to_slice(&mut buf).unwrap();
489
490 assert_eq!(encoded,
491 // &[0xBB, 24,
492 &[0xCC, 22,
493 // 0x1, 17,
494 0xAA, 15,
495 0x11, 2, 1, 2,
496 0x22, 3, 3, 4, 5,
497 0x33, 4, 6, 7, 8, 9,
498 0x2, 3,
499 0xA, 0xB, 0xC
500 ],
501 );
502
503 let t2 = T2::from_bytes(encoded).unwrap();
504
505 assert_eq!(t, t2);
506 }
507
508 // no tag
509 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
510 struct T3 {
511 // no tag
512 s: S,
513 // tag 0x02
514 t: [u8; 3],
515 }
516
517 // impl<'a> TryFrom<TaggedSlice<'a>> for T2 {
518 // type Error = Error;
519
520 // fn try_from(tagged_slice: TaggedSlice<'a>) -> Result<Self> {
521 // tagged_slice.tag().assert_eq(Tag::try_from(0xCC).unwrap())?;
522 // tagged_slice.decode_nested(|decoder| {
523 // let s = decoder.decode()?;
524 // let t = decoder.decode_tag(Tag::try_from(0x02).unwrap())?;
525
526 // Ok(Self { s, t })
527 // })
528 // }
529 // }
530
531 // impl TaggedContainer for T2 {
532 // fn tag() -> Tag {
533 // Tag::try_from(0xCC).unwrap()
534 // }
535
536 // fn fields<F, Z>(&self, field_encoder: F) -> Result<Z>
537 // where
538 // F: FnOnce(&[&dyn Encodable]) -> Result<Z>,
539 // {
540 // field_encoder(&[
541 // &self.s,
542 // &self.t.tagged(Tag::try_from(0x2).unwrap()),
543 // ])
544 // }
545 // }
546
547
548 // #[test]
549 // fn nesty3() {
550 // let s = S { x: [1,2], y: [3,4,5], z: [6,7,8,9] };
551 // let t = T3 { s, t: [0xA, 0xB, 0xC] };
552
553 // let mut buf = [0u8; 1024];
554
555 // // let encoded = (&[
556 // // &t.s,
557 // // &t.t.tagged(Tag::try_from(0x2).unwrap()),
558 // // ]).encode_to_slice(&mut buf).unwrap();
559
560 // assert_eq!(encoded,
561 // // &[0xBB, 24,
562 // &[0xCC, 22,
563 // // 0x1, 17,
564 // 0xAA, 15,
565 // 0x11, 2, 1, 2,
566 // 0x22, 3, 3, 4, 5,
567 // 0x33, 4, 6, 7, 8, 9,
568 // 0x2, 3,
569 // 0xA, 0xB, 0xC
570 // ],
571 // );
572
573 // let t2 = T2::from_bytes(encoded).unwrap();
574
575 // assert_eq!(t, t2);
576 // }
577}