picky_asn1/
wrapper.rs

1use crate::bit_string::BitString;
2use crate::date::{GeneralizedTime, UTCTime};
3use crate::restricted_string::{BmpString, Ia5String, NumericString, PrintableString, Utf8String};
4use crate::tag::Tag;
5use crate::Asn1Type;
6use oid::ObjectIdentifier;
7use serde::{de, ser, Deserialize, Serialize};
8use std::fmt;
9use std::ops::{Deref, DerefMut};
10
11/// Generate a thin ASN1 wrapper type with associated tag
12/// and name for serialization and deserialization purpose.
13macro_rules! asn1_wrapper {
14    (struct $wrapper_ty:ident ( $wrapped_ty:ident ), $tag:expr) => {
15        /// Wrapper type
16        #[derive(Debug, PartialEq, Clone)]
17        pub struct $wrapper_ty(pub $wrapped_ty);
18
19        impls! { $wrapper_ty ( $wrapped_ty ), $tag }
20    };
21    (auto struct $wrapper_ty:ident ( $wrapped_ty:ident ), $tag:expr) => {
22        /// Wrapper type
23        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
24        pub struct $wrapper_ty(pub $wrapped_ty);
25
26        impls! { $wrapper_ty ( $wrapped_ty ), $tag }
27    };
28    (special tag struct $wrapper_ty:ident < $generic:ident >, $tag:expr) => {
29        /// Wrapper type for special tag
30        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
31        pub struct $wrapper_ty<$generic>(pub $generic);
32
33        impls! { $wrapper_ty < $generic >, $tag }
34    };
35    (auto collection struct $wrapper_ty:ident < T >, $tag:expr) => {
36        /// Asn1 wrapper around a collection of elements of the same type.
37        #[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
38        pub struct $wrapper_ty<T>(
39            #[serde(
40                serialize_with = "serialize_vec",
41                deserialize_with = "deserialize_vec",
42                bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'de>")
43            )]
44            pub Vec<T>,
45        );
46
47        impl<T> Default for $wrapper_ty<T> {
48            fn default() -> Self {
49                Self(Vec::new())
50            }
51        }
52
53        impls! { $wrapper_ty ( Vec < T > ), $tag }
54    };
55}
56
57macro_rules! impls {
58    ($wrapper_ty:ident ( $wrapped_ty:ident ), $tag:expr) => {
59        impl $crate::wrapper::Asn1Type for $wrapper_ty {
60            const TAG: Tag = $tag;
61            const NAME: &'static str = stringify!($wrapper_ty);
62        }
63
64        impl From<$wrapped_ty> for $wrapper_ty {
65            fn from(wrapped: $wrapped_ty) -> Self {
66                Self(wrapped)
67            }
68        }
69
70        impl From<$wrapper_ty> for $wrapped_ty {
71            fn from(wrapper: $wrapper_ty) -> $wrapped_ty {
72                wrapper.0
73            }
74        }
75
76        impl Deref for $wrapper_ty {
77            type Target = $wrapped_ty;
78
79            fn deref(&self) -> &Self::Target {
80                &self.0
81            }
82        }
83
84        impl DerefMut for $wrapper_ty {
85            fn deref_mut(&mut self) -> &mut Self::Target {
86                &mut self.0
87            }
88        }
89
90        impl PartialEq<$wrapped_ty> for $wrapper_ty {
91            fn eq(&self, other: &$wrapped_ty) -> bool {
92                self.0.eq(other)
93            }
94        }
95    };
96    ($wrapper_ty:ident < $generic:ident >, $tag:expr) => {
97        impl<$generic> $crate::wrapper::Asn1Type for $wrapper_ty<$generic> {
98            const TAG: Tag = $tag;
99            const NAME: &'static str = stringify!($wrapper_ty);
100        }
101
102        impl<$generic> Default for $wrapper_ty<$generic>
103        where
104            $generic: Default,
105        {
106            fn default() -> Self {
107                Self($generic::default())
108            }
109        }
110
111        impl<$generic> From<$generic> for $wrapper_ty<$generic> {
112            fn from(wrapped: $generic) -> Self {
113                Self(wrapped)
114            }
115        }
116
117        //-- Into cannot be defined to convert into a generic type (E0119) --
118
119        impl<$generic> Deref for $wrapper_ty<$generic> {
120            type Target = $generic;
121
122            fn deref(&self) -> &Self::Target {
123                &self.0
124            }
125        }
126
127        impl<$generic> DerefMut for $wrapper_ty<$generic> {
128            fn deref_mut(&mut self) -> &mut Self::Target {
129                &mut self.0
130            }
131        }
132
133        impl<$generic> PartialEq<$generic> for $wrapper_ty<$generic>
134        where
135            $generic: PartialEq,
136        {
137            fn eq(&self, other: &$generic) -> bool {
138                self.0.eq(other)
139            }
140        }
141    };
142    ($wrapper_ty:ident ( $wrapped_ty:ident < $generic:ident > ), $tag:expr) => {
143        impl<$generic> $crate::wrapper::Asn1Type for $wrapper_ty<$generic> {
144            const TAG: Tag = $tag;
145            const NAME: &'static str = stringify!($wrapper_ty);
146        }
147
148        impl<$generic> From<$wrapped_ty<$generic>> for $wrapper_ty<$generic> {
149            fn from(wrapped: $wrapped_ty<$generic>) -> Self {
150                Self(wrapped)
151            }
152        }
153
154        impl<$generic> From<$wrapper_ty<$generic>> for $wrapped_ty<$generic> {
155            fn from(wrapper: $wrapper_ty<$generic>) -> Self {
156                wrapper.0
157            }
158        }
159
160        impl<$generic> Deref for $wrapper_ty<$generic> {
161            type Target = $wrapped_ty<$generic>;
162
163            fn deref(&self) -> &Self::Target {
164                &self.0
165            }
166        }
167
168        impl<$generic> DerefMut for $wrapper_ty<$generic> {
169            fn deref_mut(&mut self) -> &mut Self::Target {
170                &mut self.0
171            }
172        }
173
174        impl<$generic> PartialEq<$wrapped_ty<$generic>> for $wrapper_ty<$generic>
175        where
176            $generic: PartialEq,
177        {
178            fn eq(&self, other: &$wrapped_ty<$generic>) -> bool {
179                self.0.eq(other)
180            }
181        }
182    };
183}
184
185macro_rules! define_special_tag {
186    ( $name:ident => $tag:expr ) => {
187        asn1_wrapper! { special tag struct $name<T>, $tag }
188    };
189    ( $( $name:ident => $tag:expr , )+ ) => {
190        $( define_special_tag! { $name => $tag } )+
191    };
192}
193
194asn1_wrapper! { auto struct BitStringAsn1(BitString),               Tag::BIT_STRING }
195asn1_wrapper! { auto struct ObjectIdentifierAsn1(ObjectIdentifier), Tag::OID }
196asn1_wrapper! { auto struct Utf8StringAsn1(Utf8String),             Tag::UTF8_STRING }
197asn1_wrapper! { auto struct NumericStringAsn1(NumericString),       Tag::NUMERIC_STRING }
198asn1_wrapper! { auto struct PrintableStringAsn1(PrintableString),   Tag::PRINTABLE_STRING }
199asn1_wrapper! { auto struct Ia5StringAsn1(Ia5String),               Tag::IA5_STRING }
200asn1_wrapper! { auto struct BmpStringAsn1(BmpString),               Tag::BMP_STRING }
201asn1_wrapper! { auto struct UtcTimeAsn1(UTCTime),                   Tag::UTC_TIME }
202asn1_wrapper! { auto struct GeneralizedTimeAsn1(GeneralizedTime),   Tag::GENERALIZED_TIME }
203// [RFC 4120 5.2.1](https://www.rfc-editor.org/rfc/rfc4120.txt)
204// Kerberos specification declares General String as IA5String
205// ```not-rust
206// KerberosString  ::= GeneralString (IA5String)
207// ```
208asn1_wrapper! { auto struct GeneralStringAsn1(Ia5String),           Tag::GENERAL_STRING }
209
210#[deprecated = "Use BmpStringAsn1 instead"]
211pub use BmpStringAsn1 as BMPStringAsn1;
212#[deprecated = "Use Ia5StringAsn1 instead"]
213pub use Ia5StringAsn1 as IA5StringAsn1;
214#[deprecated = "Use UtcTimeAsn1 instead"]
215pub use UtcTimeAsn1 as UTCTimeAsn1;
216
217asn1_wrapper! { auto collection struct Asn1SequenceOf<T>, Tag::SEQUENCE }
218asn1_wrapper! { auto collection struct Asn1SetOf<T>,      Tag::SET }
219
220define_special_tag! {
221    ExplicitContextTag0  => Tag::context_specific_constructed(0),
222    ExplicitContextTag1  => Tag::context_specific_constructed(1),
223    ExplicitContextTag2  => Tag::context_specific_constructed(2),
224    ExplicitContextTag3  => Tag::context_specific_constructed(3),
225    ExplicitContextTag4  => Tag::context_specific_constructed(4),
226    ExplicitContextTag5  => Tag::context_specific_constructed(5),
227    ExplicitContextTag6  => Tag::context_specific_constructed(6),
228    ExplicitContextTag7  => Tag::context_specific_constructed(7),
229    ExplicitContextTag8  => Tag::context_specific_constructed(8),
230    ExplicitContextTag9  => Tag::context_specific_constructed(9),
231    ExplicitContextTag10 => Tag::context_specific_constructed(10),
232    ExplicitContextTag11 => Tag::context_specific_constructed(11),
233    ExplicitContextTag12 => Tag::context_specific_constructed(12),
234    ExplicitContextTag13 => Tag::context_specific_constructed(13),
235    ExplicitContextTag14 => Tag::context_specific_constructed(14),
236    ExplicitContextTag15 => Tag::context_specific_constructed(15),
237    ImplicitContextTag0  => Tag::context_specific_primitive(0),
238    ImplicitContextTag1  => Tag::context_specific_primitive(1),
239    ImplicitContextTag2  => Tag::context_specific_primitive(2),
240    ImplicitContextTag3  => Tag::context_specific_primitive(3),
241    ImplicitContextTag4  => Tag::context_specific_primitive(4),
242    ImplicitContextTag5  => Tag::context_specific_primitive(5),
243    ImplicitContextTag6  => Tag::context_specific_primitive(6),
244    ImplicitContextTag7  => Tag::context_specific_primitive(7),
245    ImplicitContextTag8  => Tag::context_specific_primitive(8),
246    ImplicitContextTag9  => Tag::context_specific_primitive(9),
247    ImplicitContextTag10 => Tag::context_specific_primitive(10),
248    ImplicitContextTag11 => Tag::context_specific_primitive(11),
249    ImplicitContextTag12 => Tag::context_specific_primitive(12),
250    ImplicitContextTag13 => Tag::context_specific_primitive(13),
251    ImplicitContextTag14 => Tag::context_specific_primitive(14),
252    ImplicitContextTag15 => Tag::context_specific_primitive(15),
253}
254
255#[allow(clippy::derivable_impls)]
256impl Default for BitStringAsn1 {
257    fn default() -> Self {
258        BitStringAsn1(BitString::default())
259    }
260}
261
262impl Default for Ia5StringAsn1 {
263    fn default() -> Self {
264        Ia5StringAsn1::from(Ia5String::default())
265    }
266}
267
268impl Default for BmpStringAsn1 {
269    fn default() -> Self {
270        BmpStringAsn1::from(BmpString::default())
271    }
272}
273
274fn serialize_vec<S, T>(elems: &[T], serializer: S) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
275where
276    S: ser::Serializer,
277    T: Serialize,
278{
279    use serde::ser::SerializeSeq;
280
281    let mut seq = serializer.serialize_seq(Some(elems.len()))?;
282    for e in elems {
283        seq.serialize_element(e)?;
284    }
285    seq.end()
286}
287
288fn deserialize_vec<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
289where
290    D: de::Deserializer<'de>,
291    T: Deserialize<'de>,
292{
293    struct Visitor<T>(std::marker::PhantomData<T>);
294
295    impl<'de, T> de::Visitor<'de> for Visitor<T>
296    where
297        T: Deserialize<'de>,
298    {
299        type Value = Vec<T>;
300
301        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
302            formatter.write_str("a valid sequence of T")
303        }
304
305        fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
306        where
307            A: de::SeqAccess<'de>,
308        {
309            let mut vec = Vec::new();
310            while let Some(e) = seq.next_element()? {
311                vec.push(e);
312            }
313            Ok(vec)
314        }
315    }
316
317    deserializer.deserialize_seq(Visitor(std::marker::PhantomData))
318}
319
320/// A Vec<u8> wrapper for Asn1 encoding as OctetString.
321#[derive(Serialize, Deserialize, PartialEq, Eq, PartialOrd, Hash, Clone, Default)]
322pub struct OctetStringAsn1(#[serde(with = "serde_bytes")] pub Vec<u8>);
323
324type VecU8 = Vec<u8>;
325impls! { OctetStringAsn1(VecU8), Tag::OCTET_STRING }
326
327impl fmt::Debug for OctetStringAsn1 {
328    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
329        write!(f, "OctetString(0x")?;
330        self.0.iter().try_for_each(|byte| write!(f, "{byte:02X}"))?;
331        write!(f, ")")?;
332
333        Ok(())
334    }
335}
336
337/// A BigInt wrapper for Asn1 encoding.
338///
339/// Simply use primitive integer types if you don't need big integer.
340///
341/// For underlying implementation,
342/// see this [Microsoft's documentation](https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-integer).
343#[derive(Serialize, Deserialize, Default, PartialEq, Eq, PartialOrd, Hash, Clone)]
344pub struct IntegerAsn1(#[serde(with = "serde_bytes")] pub Vec<u8>);
345
346impls! { IntegerAsn1(VecU8), Tag::INTEGER }
347
348// X.690-0207 Section 8.3.2:
349fn minimal_encode_start(bytes: &[u8]) -> usize {
350    let mut start = 0;
351    while start + 1 < bytes.len() {
352        if bytes[start] == 0 && (bytes[start + 1] & 0x80) == 0
353            || bytes[start] == 0xFF && (bytes[start + 1] & 0x80) == 0x80
354        {
355            start += 1;
356        } else {
357            break;
358        }
359    }
360    start
361}
362
363impl IntegerAsn1 {
364    pub fn is_positive(&self) -> bool {
365        if self.0.len() > 1 && self.0[0] == 0x00 || self.0.is_empty() {
366            true
367        } else {
368            self.0[0] & 0x80 == 0
369        }
370    }
371
372    pub fn is_negative(&self) -> bool {
373        if self.0.len() > 1 && self.0[0] == 0x00 {
374            false
375        } else if self.0.is_empty() {
376            true
377        } else {
378            self.0[0] & 0x80 != 0
379        }
380    }
381
382    pub fn as_unsigned_bytes_be(&self) -> &[u8] {
383        if self.0.len() > 1 {
384            if self.0[0] == 0x00 {
385                &self.0[1..]
386            } else {
387                &self.0
388            }
389        } else if self.0.is_empty() {
390            &[0]
391        } else {
392            &self.0
393        }
394    }
395
396    pub fn as_signed_bytes_be(&self) -> &[u8] {
397        if self.0.is_empty() {
398            &[0]
399        } else {
400            &self.0
401        }
402    }
403
404    pub fn from_bytes_be_signed(bytes: Vec<u8>) -> Self {
405        let start = minimal_encode_start(&bytes);
406        if start == 0 {
407            Self(bytes)
408        } else {
409            Self(bytes[start..].to_vec())
410        }
411    }
412
413    /// Build an ASN.1 Integer from unsigned big endian bytes.
414    ///
415    /// If high order bit is set to 1, this shift all elements to the right
416    /// and add a leading 0x00 byte indicating the number is positive.
417    /// Prefer `from_signed_bytes_be` if you can build a signed bytes string without
418    /// overhead on you side.
419    pub fn from_bytes_be_unsigned(mut bytes: Vec<u8>) -> Self {
420        if !bytes.is_empty() && bytes[0] & 0x80 == 0x80 {
421            bytes.insert(0, 0x00);
422        }
423        let start = minimal_encode_start(&bytes);
424        if start == 0 {
425            Self(bytes)
426        } else {
427            Self(bytes[start..].to_vec())
428        }
429    }
430}
431
432#[cfg(feature = "zeroize")]
433impl zeroize::Zeroize for IntegerAsn1 {
434    fn zeroize(&mut self) {
435        self.0.zeroize();
436    }
437}
438
439impl fmt::Debug for IntegerAsn1 {
440    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
441        write!(f, "Integer(0x")?;
442        self.0.iter().try_for_each(|byte| write!(f, "{byte:02X}"))?;
443        write!(f, ")")?;
444
445        Ok(())
446    }
447}
448
449/// A wrapper encoding/decoding only the header of the provided Asn1Wrapper with a length of 0.
450///
451/// Examples:
452/// ```
453/// use picky_asn1::wrapper::{ExplicitContextTag0, HeaderOnly};
454/// use serde::{Serialize, Deserialize};
455///
456/// let tag_only = HeaderOnly::<ExplicitContextTag0<()>>::default();
457/// let buffer = [0xA0, 0x00];
458///
459/// let encoded = picky_asn1_der::to_vec(&tag_only).expect("couldn't serialize");
460/// assert_eq!(
461///     encoded,
462///     buffer,
463/// );
464///
465/// let decoded: HeaderOnly<ExplicitContextTag0<()>> = picky_asn1_der::from_bytes(&buffer).expect("couldn't deserialize");
466/// assert_eq!(
467///     decoded,
468///     tag_only,
469/// );
470/// ```
471#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Hash, Clone, Default)]
472pub struct HeaderOnly<T: Asn1Type>(
473    #[serde(
474        serialize_with = "serialize_header_only",
475        deserialize_with = "deserialize_header_only",
476        bound(serialize = "T: Asn1Type", deserialize = "T: Asn1Type")
477    )]
478    pub std::marker::PhantomData<T>,
479);
480
481impl<T: Asn1Type> Asn1Type for HeaderOnly<T> {
482    const TAG: Tag = T::TAG;
483    const NAME: &'static str = "HeaderOnly";
484}
485
486#[allow(clippy::trivially_copy_pass_by_ref)]
487fn serialize_header_only<S, Phantom>(
488    _: &std::marker::PhantomData<Phantom>,
489    serializer: S,
490) -> Result<<S as ser::Serializer>::Ok, <S as ser::Serializer>::Error>
491where
492    S: ser::Serializer,
493    Phantom: Asn1Type,
494{
495    serializer.serialize_bytes(&[Phantom::TAG.inner(), 0x00][..])
496}
497
498fn deserialize_header_only<'de, D, Phantom>(deserializer: D) -> Result<std::marker::PhantomData<Phantom>, D::Error>
499where
500    D: de::Deserializer<'de>,
501    Phantom: Asn1Type,
502{
503    struct Visitor<T>(std::marker::PhantomData<T>);
504
505    impl<'de, T> de::Visitor<'de> for Visitor<T>
506    where
507        T: Asn1Type,
508    {
509        type Value = std::marker::PhantomData<T>;
510
511        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
512            formatter.write_str("a valid header for empty payload")
513        }
514
515        fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
516        where
517            E: de::Error,
518        {
519            if v.len() != 2 {
520                return Err(E::invalid_value(
521                    de::Unexpected::Other("invalid ASN.1 header length"),
522                    &"a valid buffer representing an  ASN.1 header with empty payload (two bytes)",
523                ));
524            }
525
526            if v[0] != T::TAG.inner() {
527                return Err(E::invalid_value(
528                    de::Unexpected::Other("invalid ASN.1 header: wrong tag"),
529                    &"a valid buffer representing an empty ASN.1 header (two bytes) with the expected tag",
530                ));
531            }
532
533            if v[1] != 0 {
534                return Err(E::invalid_value(
535                    de::Unexpected::Other("invalid ASN.1 header: bad payload length"),
536                    &"a valid buffer representing an empty ASN.1 header (two bytes) with no payload",
537                ));
538            }
539
540            Ok(std::marker::PhantomData)
541        }
542    }
543
544    deserializer.deserialize_bytes(Visitor(std::marker::PhantomData))
545}
546
547/// A BitString encapsulating things.
548///
549/// Same as `OctetStringAsn1Container` but using a BitString instead.
550///
551/// Useful to perform a full serialization / deserialization in one pass
552/// instead of using `BitStringAsn1` manually.
553///
554/// Examples
555/// ```
556/// use picky_asn1::wrapper::BitStringAsn1Container;
557/// use serde::{Serialize, Deserialize};
558///
559/// #[derive(Serialize, Deserialize, Debug, PartialEq)]
560/// struct MyType {
561///     a: u32,
562///     b: u16,
563///     c: u16,
564/// }
565///
566/// type MyTypeEncapsulated = BitStringAsn1Container<MyType>;
567///
568/// let encapsulated: MyTypeEncapsulated = MyType {
569///     a: 83910,
570///     b: 3839,
571///     c: 4023,
572/// }.into();
573///
574/// let buffer = [
575///     0x03, 0x10, 0x00, // bit string part
576///     0x30, 0x0d, // sequence
577///     0x02, 0x03, 0x01, 0x47, 0xc6, // integer a
578///     0x02, 0x02, 0x0e, 0xff, // integer b
579///     0x02, 0x02, 0x0f, 0xb7, // integer c
580/// ];
581///
582/// let encoded = picky_asn1_der::to_vec(&encapsulated).expect("couldn't serialize");
583/// assert_eq!(
584///     encoded,
585///     buffer,
586/// );
587///
588/// let decoded: MyTypeEncapsulated = picky_asn1_der::from_bytes(&buffer).expect("couldn't deserialize");
589/// assert_eq!(
590///     decoded,
591///     encapsulated,
592/// );
593/// ```
594#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Hash, Clone)]
595pub struct BitStringAsn1Container<Encapsulated>(pub Encapsulated);
596
597impls! { BitStringAsn1Container<Encapsulated>, Tag::BIT_STRING }
598
599/// An OctetString encapsulating things.
600///
601/// Same as `BitStringAsn1Container` but using an OctetString instead.
602///
603/// Useful to perform a full serialization / deserialization in one pass
604/// instead of using `OctetStringAsn1` manually.
605///
606/// Examples
607/// ```
608/// use picky_asn1::wrapper::OctetStringAsn1Container;
609/// use serde::{Serialize, Deserialize};
610///
611/// #[derive(Serialize, Deserialize, Debug, PartialEq)]
612/// struct MyType {
613///     a: u32,
614///     b: u16,
615///     c: u16,
616/// }
617///
618/// type MyTypeEncapsulated = OctetStringAsn1Container<MyType>;
619///
620/// let encapsulated: MyTypeEncapsulated = MyType {
621///     a: 83910,
622///     b: 3839,
623///     c: 4023,
624/// }.into();
625///
626/// let buffer = [
627///     0x04, 0x0F, // octet string part
628///     0x30, 0x0d, // sequence
629///     0x02, 0x03, 0x01, 0x47, 0xc6, // integer a
630///     0x02, 0x02, 0x0e, 0xff, // integer b
631///     0x02, 0x02, 0x0f, 0xb7, // integer c
632/// ];
633///
634/// let encoded = picky_asn1_der::to_vec(&encapsulated).expect("couldn't serialize");
635/// assert_eq!(
636///     encoded,
637///     buffer,
638/// );
639///
640/// let decoded: MyTypeEncapsulated = picky_asn1_der::from_bytes(&buffer).expect("couldn't deserialize");
641/// assert_eq!(
642///     decoded,
643///     encapsulated,
644/// );
645/// ```
646#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Hash, Clone)]
647pub struct OctetStringAsn1Container<Encapsulated>(pub Encapsulated);
648
649impls! { OctetStringAsn1Container<Encapsulated>, Tag::OCTET_STRING }
650
651/// Wrapper for ASN.1 optionals fields
652///
653/// Wrapped type has to implement the Default trait to be deserializable (on deserialization failure
654/// a default value is returned).
655///
656/// Examples:
657/// ```
658/// use picky_asn1::wrapper::{Optional, ExplicitContextTag0};
659/// use serde::{Serialize, Deserialize};
660///
661/// #[derive(Serialize, Deserialize, Debug, PartialEq)]
662/// struct MyWrapper(u8);
663///
664/// impl Default for MyWrapper {
665///     fn default() -> Self {
666///         Self(10)
667///     }
668/// }
669///
670/// #[derive(Serialize, Deserialize, Debug, PartialEq)]
671/// struct ComplexType {
672///     // skip if default to reduce encoded size
673///     #[serde(skip_serializing_if = "optional_field_is_default")]
674///     optional_field: Optional<MyWrapper>,
675///     // behind application tag 0 to distinguish from optional_field that is a ASN.1 integer too.
676///     explicit_field: ExplicitContextTag0<u8>,
677/// }
678///
679/// fn optional_field_is_default(wrapper: &Optional<MyWrapper>) -> bool {
680///     wrapper.0 == MyWrapper::default()
681/// }
682///
683/// let complex_type = ComplexType {
684///     optional_field: MyWrapper::default().into(),
685///     explicit_field: 5.into(),
686/// };
687///
688/// let buffer = [
689///     0x30, 0x05, // sequence
690///     // optional field isn't present
691///     0xA0, 0x03, 0x02, 0x01, 0x05, // explicit field
692/// ];
693///
694/// let encoded = picky_asn1_der::to_vec(&complex_type).expect("couldn't serialize");
695/// assert_eq!(
696///     encoded,
697///     buffer,
698/// );
699///
700/// let decoded: ComplexType = picky_asn1_der::from_bytes(&buffer).expect("couldn't deserialize");
701/// assert_eq!(
702///     decoded,
703///     complex_type,
704/// );
705/// ```
706#[derive(Debug, PartialEq, Eq, PartialOrd, Hash, Clone)]
707pub struct Optional<T>(pub T);
708
709impl<T: Default> Default for Optional<T> {
710    fn default() -> Self {
711        Optional(T::default())
712    }
713}
714
715impl<T> Optional<T>
716where
717    T: Default + PartialEq,
718{
719    pub fn is_default(&self) -> bool {
720        self.0 == T::default()
721    }
722}
723
724impl<T> From<T> for Optional<T> {
725    fn from(wrapped: T) -> Self {
726        Self(wrapped)
727    }
728}
729
730impl<T> Deref for Optional<T> {
731    type Target = T;
732
733    fn deref(&self) -> &Self::Target {
734        &self.0
735    }
736}
737
738impl<T> DerefMut for Optional<T> {
739    fn deref_mut(&mut self) -> &mut Self::Target {
740        &mut self.0
741    }
742}
743
744impl<T> PartialEq<T> for Optional<T>
745where
746    T: PartialEq,
747{
748    fn eq(&self, other: &T) -> bool {
749        self.0.eq(other)
750    }
751}
752
753impl<T> Serialize for Optional<T>
754where
755    T: Serialize,
756{
757    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
758    where
759        S: ser::Serializer,
760    {
761        self.0.serialize(serializer)
762    }
763}
764
765impl<'de, T> Deserialize<'de> for Optional<T>
766where
767    T: Deserialize<'de> + Default,
768{
769    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
770    where
771        D: de::Deserializer<'de>,
772    {
773        struct Visitor<T>(std::marker::PhantomData<T>);
774
775        impl<'de, T> de::Visitor<'de> for Visitor<T>
776        where
777            T: Deserialize<'de>,
778        {
779            type Value = Optional<T>;
780
781            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
782                write!(formatter, "nothing or a valid DER-encoded T")
783            }
784
785            fn visit_newtype_struct<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
786            where
787                D: de::Deserializer<'de>,
788            {
789                T::deserialize(deserializer).map(Optional::from)
790            }
791        }
792
793        match deserializer.deserialize_newtype_struct("Optional", Visitor(std::marker::PhantomData)) {
794            Err(_) => Ok(Self(T::default())),
795            result => result,
796        }
797    }
798}
799
800#[cfg(test)]
801mod tests {
802    use super::*;
803
804    #[test]
805    fn integer_from_unsigned_bytes_be_no_panic() {
806        IntegerAsn1::from_bytes_be_unsigned(vec![]);
807    }
808
809    #[test]
810    fn minimal_encode_start_positive() {
811        // Open question: shouldn't we replace a zero length "integer" with
812        // 0x00 octet?
813        assert_eq!(minimal_encode_start(b""), 0);
814        assert_eq!(minimal_encode_start(b"\x00"), 0);
815        assert_eq!(minimal_encode_start(b"\x00\x00"), 1);
816        assert_eq!(minimal_encode_start(b"\x00\x00\x00"), 2);
817        assert_eq!(minimal_encode_start(b"\x00\x00\x80"), 1);
818    }
819
820    #[test]
821    fn minimal_encode_start_negative() {
822        assert_eq!(minimal_encode_start(b"\xFF"), 0);
823        assert_eq!(minimal_encode_start(b"\xFF\x00"), 0);
824        assert_eq!(minimal_encode_start(b"\xFF\x80"), 1);
825        assert_eq!(minimal_encode_start(b"\xFF\xFF\x00"), 1);
826        assert_eq!(minimal_encode_start(b"\xFF\xFF\x80"), 2);
827    }
828}