diff --git a/der/tests/derive.rs b/der/tests/derive.rs index d2d677071..a8617434c 100644 --- a/der/tests/derive.rs +++ b/der/tests/derive.rs @@ -441,8 +441,19 @@ mod sequence { pub typed: &'a [u8], #[asn1(context_specific = "0")] pub context_specific: bool, + #[asn1(optional = "true")] pub optional: Option, + + #[asn1(type = "OCTET STRING", optional = "true")] + pub optional_octet_string: Option<&'a [u8]>, + + #[asn1(type = "BIT STRING", optional = "true")] + pub optional_bit_string: Option<&'a [u8]>, + + #[asn1(optional = "true")] + pub optional_oid: Option, + #[asn1(default = "default_false_example")] pub default: bool, #[asn1(type = "BIT STRING", context_specific = "1")] @@ -467,6 +478,9 @@ mod sequence { #[test] fn type_combinations_instance() { let obj = TypeCheckExpandedSequenceFieldAttributeCombinations { + optional: Some(true), + optional_octet_string: Some(&[0xAA, 0xBB]), + optional_bit_string: Some(&[0xCC, 0xDD]), context_specific_optional: Some(true), typed_context_specific: &[0, 1], typed_context_specific_optional_bits: Some(&[2, 3]), @@ -477,6 +491,7 @@ mod sequence { }; let der_encoded = obj.to_der().unwrap(); + let obj_decoded = TypeCheckExpandedSequenceFieldAttributeCombinations::from_der(&der_encoded).unwrap(); assert_eq!(obj, obj_decoded); diff --git a/der_derive/src/asn1_type.rs b/der_derive/src/asn1_type.rs index f61d72487..2acee3fc8 100644 --- a/der_derive/src/asn1_type.rs +++ b/der_derive/src/asn1_type.rs @@ -54,17 +54,13 @@ impl Asn1Type { /// Get a `der::Decoder` object for a particular ASN.1 type pub fn decoder(self) -> TokenStream { - match self { - Asn1Type::BitString => quote!(::der::asn1::BitStringRef::decode(reader)?), - Asn1Type::Ia5String => quote!(::der::asn1::Ia5StringRef::decode(reader)?), - Asn1Type::GeneralizedTime => quote!(::der::asn1::GeneralizedTime::decode(reader)?), - Asn1Type::OctetString => quote!(::der::asn1::OctetStringRef::decode(reader)?), - Asn1Type::PrintableString => quote!(::der::asn1::PrintableStringRef::decode(reader)?), - Asn1Type::TeletexString => quote!(::der::asn1::TeletexStringRef::decode(reader)?), - Asn1Type::VideotexString => quote!(::der::asn1::VideotexStringRef::decode(reader)?), - Asn1Type::UtcTime => quote!(::der::asn1::UtcTime::decode(reader)?), - Asn1Type::Utf8String => quote!(::der::asn1::Utf8StringRef::decode(reader)?), - } + let type_path = self.type_path(); + quote!(#type_path::decode(reader)?) + } + /// Get a `der::Decoder` optional object for a particular ASN.1 type + pub fn decoder_optional(self) -> TokenStream { + let type_path = self.type_path(); + quote!(Option::<#type_path>::decode(reader)?) } /// Get a `der::Encoder` object for a particular ASN.1 type diff --git a/der_derive/src/attributes.rs b/der_derive/src/attributes.rs index ffc1b7e09..181a7b2f4 100644 --- a/der_derive/src/attributes.rs +++ b/der_derive/src/attributes.rs @@ -299,6 +299,10 @@ impl FieldAttrs { Option::<#type_params>::decode(reader)?.unwrap_or_else(#default), } }) + } else if self.is_optional() { + self.asn1_type + .map(|ty| ty.decoder_optional()) + .unwrap_or_else(|| quote!(reader.decode()?)) } else { self.asn1_type .map(|ty| ty.decoder())