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