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