der/asn1/
optional.rs

1//! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type
2
3use crate::{Choice, Decode, DerOrd, Encode, Length, Reader, Result, Tag, Writer};
4use core::cmp::Ordering;
5
6impl<'a, T> Decode<'a> for Option<T>
7where
8    T: Choice<'a>, // NOTE: all `Decode + Tagged` types receive a blanket `Choice` impl
9{
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
21impl<T> DerOrd for Option<T>
22where
23    T: DerOrd,
24{
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
36impl<T> Encode for Option<T>
37where
38    T: Encode,
39{
40    fn encoded_len(&self) -> Result<Length> {
41        (&self).encoded_len()
42    }
43
44    fn encode(&self, writer: &mut impl Writer) -> Result<()> {
45        (&self).encode(writer)
46    }
47}
48
49impl<T> Encode for &Option<T>
50where
51    T: Encode,
52{
53    fn encoded_len(&self) -> Result<Length> {
54        match self {
55            Some(encodable) => encodable.encoded_len(),
56            None => Ok(0u8.into()),
57        }
58    }
59
60    fn encode(&self, encoder: &mut impl Writer) -> Result<()> {
61        match self {
62            Some(encodable) => encodable.encode(encoder),
63            None => Ok(()),
64        }
65    }
66}