1 //! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type
2 
3 use crate::{Choice, Decode, DerOrd, Encode, Length, Reader, Result, Tag, Writer};
4 use core::cmp::Ordering;
5 
6 impl<'a, T> Decode<'a> for Option<T>
7 where
8     T: Choice<'a>, // NOTE: all `Decode + Tagged` types receive a blanket `Choice` impl
9 {
decode<R: Reader<'a>>(reader: &mut R) -> Result<Option<T>>10     fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Option<T>> {
11         if let Some(byte) = reader.peek_byte() {
12             if T::can_decode(Tag::try_from(byte)?) {
13                 return T::decode(reader).map(Some);
14             }
15         }
16 
17         Ok(None)
18     }
19 }
20 
21 impl<T> DerOrd for Option<T>
22 where
23     T: DerOrd,
24 {
der_cmp(&self, other: &Self) -> Result<Ordering>25     fn der_cmp(&self, other: &Self) -> Result<Ordering> {
26         match self {
27             Some(a) => match other {
28                 Some(b) => a.der_cmp(b),
29                 None => Ok(Ordering::Greater),
30             },
31             None => Ok(Ordering::Less),
32         }
33     }
34 }
35 
36 impl<T> Encode for Option<T>
37 where
38     T: Encode,
39 {
encoded_len(&self) -> Result<Length>40     fn encoded_len(&self) -> Result<Length> {
41         (&self).encoded_len()
42     }
43 
encode(&self, writer: &mut impl Writer) -> Result<()>44     fn encode(&self, writer: &mut impl Writer) -> Result<()> {
45         (&self).encode(writer)
46     }
47 }
48 
49 impl<T> Encode for &Option<T>
50 where
51     T: Encode,
52 {
encoded_len(&self) -> Result<Length>53     fn encoded_len(&self) -> Result<Length> {
54         match self {
55             Some(encodable) => encodable.encoded_len(),
56             None => Ok(0u8.into()),
57         }
58     }
59 
encode(&self, encoder: &mut impl Writer) -> Result<()>60     fn encode(&self, encoder: &mut impl Writer) -> Result<()> {
61         match self {
62             Some(encodable) => encodable.encode(encoder),
63             None => Ok(()),
64         }
65     }
66 }
67