diff options
Diffstat (limited to 'vendor/der/src/asn1/optional.rs')
-rw-r--r-- | vendor/der/src/asn1/optional.rs | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/vendor/der/src/asn1/optional.rs b/vendor/der/src/asn1/optional.rs new file mode 100644 index 0000000..ecda4f8 --- /dev/null +++ b/vendor/der/src/asn1/optional.rs @@ -0,0 +1,66 @@ +//! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type + +use crate::{Choice, Decode, DerOrd, Encode, Length, Reader, Result, Tag, Writer}; +use core::cmp::Ordering; + +impl<'a, T> Decode<'a> for Option<T> +where + T: Choice<'a>, // NOTE: all `Decode + Tagged` types receive a blanket `Choice` impl +{ + fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Option<T>> { + if let Some(byte) = reader.peek_byte() { + if T::can_decode(Tag::try_from(byte)?) { + return T::decode(reader).map(Some); + } + } + + Ok(None) + } +} + +impl<T> DerOrd for Option<T> +where + T: DerOrd, +{ + fn der_cmp(&self, other: &Self) -> Result<Ordering> { + match self { + Some(a) => match other { + Some(b) => a.der_cmp(b), + None => Ok(Ordering::Greater), + }, + None => Ok(Ordering::Less), + } + } +} + +impl<T> Encode for Option<T> +where + T: Encode, +{ + fn encoded_len(&self) -> Result<Length> { + (&self).encoded_len() + } + + fn encode(&self, writer: &mut impl Writer) -> Result<()> { + (&self).encode(writer) + } +} + +impl<T> Encode for &Option<T> +where + T: Encode, +{ + fn encoded_len(&self) -> Result<Length> { + match self { + Some(encodable) => encodable.encoded_len(), + None => Ok(0u8.into()), + } + } + + fn encode(&self, encoder: &mut impl Writer) -> Result<()> { + match self { + Some(encodable) => encodable.encode(encoder), + None => Ok(()), + } + } +} |