der/asn1/
optional.rs

1//! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type
2
3use crate::{Choice, Decodable, Decoder, DerOrd, Encodable, Encoder, Length, Result, Tag};
4use core::cmp::Ordering;
5
6impl<'a, T> Decodable<'a> for Option<T>
7where
8    T: Choice<'a>, // NOTE: all `Decodable + Tagged` types receive a blanket `Choice` impl
9{
10    fn decode(decoder: &mut Decoder<'a>) -> Result<Option<T>> {
11        if let Some(byte) = decoder.peek_byte() {
12            if T::can_decode(Tag::try_from(byte)?) {
13                return T::decode(decoder).map(Some);
14            }
15        }
16
17        Ok(None)
18    }
19}
20
21impl<T> Encodable for Option<T>
22where
23    T: Encodable,
24{
25    fn encoded_len(&self) -> Result<Length> {
26        if let Some(encodable) = self {
27            encodable.encoded_len()
28        } else {
29            Ok(0u8.into())
30        }
31    }
32
33    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
34        if let Some(encodable) = self {
35            encodable.encode(encoder)
36        } else {
37            Ok(())
38        }
39    }
40}
41
42impl<T> DerOrd for Option<T>
43where
44    T: DerOrd,
45{
46    fn der_cmp(&self, other: &Self) -> Result<Ordering> {
47        if let Some(a) = self {
48            if let Some(b) = other {
49                a.der_cmp(b)
50            } else {
51                Ok(Ordering::Greater)
52            }
53        } else {
54            Ok(Ordering::Less)
55        }
56    }
57}
58
59/// A reference to an ASN.1 `OPTIONAL` type, used for encoding only.
60pub struct OptionalRef<'a, T>(pub Option<&'a T>);
61
62impl<'a, T> Encodable for OptionalRef<'a, T>
63where
64    T: Encodable,
65{
66    fn encoded_len(&self) -> Result<Length> {
67        if let Some(encodable) = self.0 {
68            encodable.encoded_len()
69        } else {
70            Ok(0u8.into())
71        }
72    }
73
74    fn encode(&self, encoder: &mut Encoder<'_>) -> Result<()> {
75        if let Some(encodable) = self.0 {
76            encodable.encode(encoder)
77        } else {
78            Ok(())
79        }
80    }
81}