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}