asn1_rs/asn1_types/
optional.rs

1use crate::*;
2
3// note: we cannot implement `TryFrom<Any<'a>> with generic errors for Option<T>`,
4// because this conflicts with generic `T` implementation in
5// `src/traits.rs`, since `T` always satisfies `T: Into<Option<T>>`
6//
7// for the same reason, we cannot use a generic error type here
8impl<'a, T> FromBer<'a> for Option<T>
9where
10    T: FromBer<'a>,
11    T: Tagged,
12{
13    fn from_ber(bytes: &'a [u8]) -> ParseResult<Self> {
14        if bytes.is_empty() {
15            return Ok((bytes, None));
16        }
17        if let Ok((_, header)) = Header::from_ber(bytes) {
18            if T::TAG != header.tag {
19                // not the expected tag, early return
20                return Ok((bytes, None));
21            }
22        }
23        match T::from_ber(bytes) {
24            Ok((rem, t)) => Ok((rem, Some(t))),
25            Err(e) => Err(e),
26        }
27    }
28}
29
30impl<'a> FromBer<'a> for Option<Any<'a>> {
31    fn from_ber(bytes: &'a [u8]) -> ParseResult<Self> {
32        if bytes.is_empty() {
33            return Ok((bytes, None));
34        }
35        match Any::from_ber(bytes) {
36            Ok((rem, t)) => Ok((rem, Some(t))),
37            Err(e) => Err(e),
38        }
39    }
40}
41
42impl<'a, T> FromDer<'a> for Option<T>
43where
44    T: FromDer<'a>,
45    T: Tagged,
46{
47    fn from_der(bytes: &'a [u8]) -> ParseResult<Self> {
48        if bytes.is_empty() {
49            return Ok((bytes, None));
50        }
51        if let Ok((_, header)) = Header::from_der(bytes) {
52            if T::TAG != header.tag {
53                // not the expected tag, early return
54                return Ok((bytes, None));
55            }
56        }
57        match T::from_der(bytes) {
58            Ok((rem, t)) => Ok((rem, Some(t))),
59            Err(e) => Err(e),
60        }
61    }
62}
63
64impl<'a> FromDer<'a> for Option<Any<'a>> {
65    fn from_der(bytes: &'a [u8]) -> ParseResult<Self> {
66        if bytes.is_empty() {
67            return Ok((bytes, None));
68        }
69        match Any::from_der(bytes) {
70            Ok((rem, t)) => Ok((rem, Some(t))),
71            Err(e) => Err(e),
72        }
73    }
74}
75
76impl<T> CheckDerConstraints for Option<T>
77where
78    T: CheckDerConstraints,
79{
80    fn check_constraints(any: &Any) -> Result<()> {
81        T::check_constraints(any)
82    }
83}
84
85impl<T> DynTagged for Option<T>
86where
87    T: DynTagged,
88{
89    fn tag(&self) -> Tag {
90        if self.is_some() {
91            self.tag()
92        } else {
93            Tag(0)
94        }
95    }
96}
97
98#[cfg(feature = "std")]
99impl<T> ToDer for Option<T>
100where
101    T: ToDer,
102{
103    fn to_der_len(&self) -> Result<usize> {
104        match self {
105            None => Ok(0),
106            Some(t) => t.to_der_len(),
107        }
108    }
109
110    fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
111        match self {
112            None => Ok(0),
113            Some(t) => t.write_der_header(writer),
114        }
115    }
116
117    fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
118        match self {
119            None => Ok(0),
120            Some(t) => t.write_der_content(writer),
121        }
122    }
123}