diff --git a/Cargo.lock b/Cargo.lock index ccc98980..4335a955 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -173,9 +173,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cast" @@ -1034,18 +1034,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" dependencies = [ "proc-macro2", "quote", @@ -1094,9 +1094,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", diff --git a/macros/src/config.rs b/macros/src/config.rs index 12a2497b..f92cc059 100644 --- a/macros/src/config.rs +++ b/macros/src/config.rs @@ -916,17 +916,18 @@ impl<'a> FieldConfig<'a> { self.constraints.has_constraints(), ) { (Some(true), _, _) => { - let or_else = if self.is_option_type() { - quote!(.ok()) + if self.is_option_type() { + quote!( + decoder.decode_optional_with_explicit_prefix(#tag)? + ) } else if self.is_default_type() { - quote!(.ok().unwrap_or_else(#default_fn)) + quote!( + decoder.decode_optional_with_explicit_prefix(#tag)?.unwrap_or_else(#default_fn) + ) } else { // False positive - #[allow(clippy::redundant_clone)] - or_else.clone() - }; - - quote!(decoder.decode_explicit_prefix(#tag) #or_else) + quote!(decoder.decode_explicit_prefix(#tag) #or_else) + } } (Some(false), Some(path), true) => { quote!( @@ -979,13 +980,61 @@ impl<'a> FieldConfig<'a> { if self.extension_addition { match ( + (self.tag.is_some() || self.container_config.automatic_tags) + .then(|| self.tag.as_ref().map_or(false, |tag| tag.is_explicit())), self.default.as_ref().map(|path| { path.as_ref() .map_or(quote!(<_>::default), |path| quote!(#path)) }), self.constraints.has_constraints(), ) { - (Some(path), true) => { + (Some(true), _, constraints) => { + let or_else = if self.is_option_type() { + quote!(.ok()) + } else if self.is_default_type() { + quote!(.ok().unwrap_or_else(#default_fn)) + } else { + // False positive + #[allow(clippy::redundant_clone)] + or_else.clone() + }; + if constraints { + quote!( + decoder.decode_extension_addition_with_explicit_tag_and_constraints( + #tag, + <#ty as #crate_root::AsnType>::CONSTRAINTS.override_constraints(#constraints), + ) #or_else #handle_extension) + } else { + quote!(decoder.decode_extension_addition_with_explicit_tag_and_constraints( + #tag, + <#ty as #crate_root::AsnType>::CONSTRAINTS) #or_else #handle_extension) + } + } + (Some(false), Some(path), true) => { + quote!( + decoder.decode_extension_addition_with_default_and_tag_and_constraints( + #tag, + #path, + <#ty as #crate_root::AsnType>::CONSTRAINTS.override_constraints(#constraints), + ) #or_else + ) + } + (Some(false), None, true) => { + quote!( + <_>::decode_extension_addition_with_tag_and_constraints( + decoder, + #tag, + <#ty as #crate_root::AsnType>::CONSTRAINTS.override_constraints(#constraints), + ) #or_else #handle_extension + ) + } + (Some(false), Some(path), false) => { + quote!(decoder.decode_extension_addition_with_default_and_tag(#tag, #path) #or_else) + } + (Some(false), None, false) => { + quote!(<_>::decode_extension_addition_with_tag(decoder, #tag) #or_else #handle_extension) + } + (None, Some(path), true) => { quote!( decoder.decode_extension_addition_with_default_and_constraints( #path, @@ -993,21 +1042,21 @@ impl<'a> FieldConfig<'a> { ) #or_else ) } - (Some(path), false) => { + (None, Some(path), false) => { quote!( decoder.decode_extension_addition_with_default( #path, ) #or_else ) } - (None, true) => { + (None, None, true) => { quote!( decoder.decode_extension_addition_with_constraints( <#ty as #crate_root::AsnType>::CONSTRAINTS.override_constraints(#constraints), ) #or_else ) } - (None, false) => { + (None, None, false) => { quote! { decoder.decode_extension_addition() #or_else #handle_extension } diff --git a/src/aper.rs b/src/aper.rs index a6b8c270..ffa55c8c 100644 --- a/src/aper.rs +++ b/src/aper.rs @@ -489,6 +489,10 @@ mod tests { }; let encoded = rasn::aper::encode(&connect_data).expect("failed to encode"); + assert_eq!( + encoded, + vec![0x00, 0x05, 0x00, 0x14, 0x7C, 0x00, 0x01, 0x04, 0x00, 0x01, 0x02, 0x03] + ); let _: ConnectData = rasn::aper::decode(&encoded).expect("failed to decode"); } } diff --git a/src/ber.rs b/src/ber.rs index 2ef4103a..2618ce38 100644 --- a/src/ber.rs +++ b/src/ber.rs @@ -383,4 +383,38 @@ mod tests { &[0x1f, 0x1f, 0x08, 0x32, 0x30, 0x31, 0x32, 0x31, 0x32, 0x32, 0x31] ); } + #[test] + fn test_extended_sequence() { + use crate as rasn; + use rasn::prelude::*; + #[derive(AsnType, Debug, Clone, Encode, Decode, PartialEq)] + #[rasn(automatic_tags)] + #[non_exhaustive] + pub struct ExtendedInteger { + #[rasn(extension_addition)] + pub extension: Option, + } + round_trip!( + ber, + ExtendedInteger, + ExtendedInteger { + extension: Some(42) + }, + &[0x30, 0x03, 0x80, 0x01, 0x2A] + ); + #[derive(AsnType, Debug, Clone, Encode, Decode, PartialEq)] + #[non_exhaustive] + pub struct ExtendedExplicitInteger { + #[rasn(extension_addition)] + #[rasn(tag(explicit(5)))] + pub extension: u64, + } + + round_trip!( + ber, + ExtendedExplicitInteger, + ExtendedExplicitInteger { extension: 42 }, + &[0x30, 0x05, 0xA5, 0x03, 0x02, 0x01, 0x2A] + ); + } } diff --git a/src/ber/de.rs b/src/ber/de.rs index 9cc4ea65..c6306b6e 100644 --- a/src/ber/de.rs +++ b/src/ber/de.rs @@ -652,7 +652,7 @@ impl crate::Decoder for Decoder<'_> { // If there are no fields, or the input is empty and we know that // all fields are optional or default fields, we call the default // initializer and skip calling the decode function at all. - if D::FIELDS.is_empty() + if D::FIELDS.is_empty() && D::EXTENDED_FIELDS.is_none() || (D::FIELDS.len() == D::FIELDS.number_of_optional_and_default_fields() && decoder.input.is_empty()) { @@ -671,6 +671,14 @@ impl crate::Decoder for Decoder<'_> { fn decode_explicit_prefix(&mut self, tag: Tag) -> Result { self.parse_constructed_contents(tag, false, D::decode) } + fn decode_optional_with_explicit_prefix( + &mut self, + tag: Tag, + ) -> Result, Self::Error> { + self.decode_explicit_prefix(tag) + .map(Some) + .or_else(|_| Ok(None)) + } fn decode_set( &mut self, @@ -736,15 +744,27 @@ impl crate::Decoder for Decoder<'_> { D::from_tag(self, identifier.tag) } - fn decode_extension_addition_with_constraints( + fn decode_extension_addition_with_explicit_tag_and_constraints( + &mut self, + tag: Tag, + _constraints: Constraints, + ) -> core::result::Result, Self::Error> + where + D: Decode, + { + self.decode_explicit_prefix(tag).map(Some) + } + + fn decode_extension_addition_with_tag_and_constraints( &mut self, + tag: Tag, // Constraints are irrelevant using BER _: Constraints, ) -> core::result::Result, Self::Error> where D: Decode, { - >::decode(self) + >::decode_with_tag(self, tag) } fn decode_extension_addition_group( diff --git a/src/coer.rs b/src/coer.rs index d294ed09..d0bcb3d6 100644 --- a/src/coer.rs +++ b/src/coer.rs @@ -1296,6 +1296,26 @@ mod tests { }, &[0b10000000, 0x01, 0x01, 0x03, 0x01, 0x02, 0x03] ); + + #[derive(AsnType, Decode, Encode, Clone, Debug, PartialEq, Eq)] + pub struct SequenceOptionalsExplicit { + #[rasn(tag(explicit(0)))] + pub it: Integer, + #[rasn(tag(explicit(1)))] + pub is: Option, + #[rasn(tag(explicit(2)))] + pub late: Option, + } + round_trip!( + coer, + SequenceOptionalsExplicit, + SequenceOptionalsExplicit { + it: 42.into(), + is: None, + late: None + }, + &[0, 1, 42] + ); #[derive(AsnType, Decode, Encode, Clone, Debug, PartialEq, Eq)] #[non_exhaustive] pub struct SequenceDuplicatesExtended { diff --git a/src/de.rs b/src/de.rs index 6031271d..8e832983 100644 --- a/src/de.rs +++ b/src/de.rs @@ -182,6 +182,11 @@ pub trait Decoder: Sized { /// Decode an ASN.1 value that has been explicitly prefixed with `tag` from the available input. fn decode_explicit_prefix(&mut self, tag: Tag) -> Result; + /// Decode an optional ASN.1 type that has been explicitly prefixed with `tag` from the available input. + fn decode_optional_with_explicit_prefix( + &mut self, + tag: Tag, + ) -> Result, Self::Error>; /// Decode a `UtcTime` identified by `tag` from the available input. fn decode_utc_time(&mut self, tag: Tag) -> Result; /// Decode a `GeneralizedTime` identified by `tag` from the available input. @@ -276,13 +281,47 @@ pub trait Decoder: Sized { .unwrap_or_else(default_fn)) } - /// Decode a extension addition value in a `SEQUENCE` or `SET`. + /// Decode an extension addition value in a `SEQUENCE` or `SET`. fn decode_extension_addition(&mut self) -> Result, Self::Error> where D: Decode, { self.decode_extension_addition_with_constraints(Constraints::default()) } + /// Decode an extension addition with explicit tag in a `SEQUENCE` or `SET`. + fn decode_extension_addition_with_explicit_tag_and_constraints( + &mut self, + tag: Tag, + constraints: Constraints, + ) -> Result, Self::Error> + where + D: Decode; + + /// Decode an extension addition value with tag in a `SEQUENCE` or `SET`. + fn decode_extension_addition_with_tag(&mut self, tag: Tag) -> Result, Self::Error> + where + D: Decode, + { + self.decode_extension_addition_with_tag_and_constraints(tag, Constraints::default()) + } + /// Decode an extension addition with constraints in a `SEQUENCE` or `SET` + fn decode_extension_addition_with_constraints( + &mut self, + constraints: Constraints, + ) -> Result, Self::Error> + where + D: Decode, + { + self.decode_extension_addition_with_tag_and_constraints(D::TAG, constraints) + } + /// Decode a extension addition value with tag and constraints in a `SEQUENCE` or `SET`. + fn decode_extension_addition_with_tag_and_constraints( + &mut self, + tag: Tag, + constraints: Constraints, + ) -> Result, Self::Error> + where + D: Decode; /// Decode a `DEFAULT` value in a `SEQUENCE`'s or `SET`'s extension fn decode_extension_addition_with_default D>( @@ -294,6 +333,18 @@ pub trait Decoder: Sized { Constraints::default(), ) } + /// Decode a `DEFAULT` value with tag in a `SEQUENCE`'s or `SET`'s extension + fn decode_extension_addition_with_default_and_tag D>( + &mut self, + tag: Tag, + default_fn: F, + ) -> Result { + self.decode_extension_addition_with_default_and_tag_and_constraints::( + tag, + default_fn, + Constraints::default(), + ) + } /// Decode a `DEFAULT` value with constraints in a `SEQUENCE`'s or `SET`'s extension fn decode_extension_addition_with_default_and_constraints D>( @@ -305,14 +356,20 @@ pub trait Decoder: Sized { .decode_extension_addition_with_constraints::(constraints)? .unwrap_or_else(default_fn)) } - - /// Decode an extension addition with constraints in a `SEQUENCE` or `SET` - fn decode_extension_addition_with_constraints( + /// Decode a `DEFAULT` value with tag and constraints in a `SEQUENCE`'s or `SET`'s extension + fn decode_extension_addition_with_default_and_tag_and_constraints< + D: Decode, + F: FnOnce() -> D, + >( &mut self, + tag: Tag, + default_fn: F, constraints: Constraints, - ) -> Result, Self::Error> - where - D: Decode; + ) -> Result { + Ok(self + .decode_extension_addition_with_tag_and_constraints::(tag, constraints)? + .unwrap_or_else(default_fn)) + } /// Decode a extension addition group in a `SEQUENCE` or `SET`. fn decode_extension_addition_group( diff --git a/src/jer/de.rs b/src/jer/de.rs index 38fb0f7a..2980080d 100644 --- a/src/jer/de.rs +++ b/src/jer/de.rs @@ -293,6 +293,12 @@ impl crate::Decoder for Decoder { ) }) } + fn decode_optional_with_explicit_prefix( + &mut self, + _: Tag, + ) -> Result, Self::Error> { + self.decode_optional() + } fn decode_explicit_prefix(&mut self, _t: Tag) -> Result { D::decode(self) @@ -395,8 +401,20 @@ impl crate::Decoder for Decoder { self.decode_optional() } - fn decode_extension_addition_with_constraints( + fn decode_extension_addition_with_explicit_tag_and_constraints( + &mut self, + tag: Tag, + constraints: Constraints, + ) -> core::result::Result, Self::Error> + where + D: Decode, + { + self.decode_extension_addition_with_tag_and_constraints::(tag, constraints) + } + + fn decode_extension_addition_with_tag_and_constraints( &mut self, + _: Tag, _: Constraints, ) -> Result, Self::Error> where diff --git a/src/oer/de.rs b/src/oer/de.rs index fa4af0da..540d0506 100644 --- a/src/oer/de.rs +++ b/src/oer/de.rs @@ -771,9 +771,20 @@ impl crate::Decoder for Decoder<'_> { ) -> Result { self.parse_known_multiplier_string(&constraints) } + fn decode_optional_with_explicit_prefix( + &mut self, + tag: Tag, + ) -> Result, Self::Error> { + self.decode_optional_with_tag(tag) + } - fn decode_explicit_prefix(&mut self, _tag: Tag) -> Result { - D::decode(self) + fn decode_explicit_prefix(&mut self, tag: Tag) -> Result { + // Whether we have a choice here + if D::TAG == Tag::EOC { + D::decode(self) + } else { + D::decode_with_tag(self, tag) + } } fn decode_utc_time(&mut self, tag: Tag) -> Result { @@ -938,9 +949,20 @@ impl crate::Decoder for Decoder<'_> { Ok(None) } } + fn decode_extension_addition_with_explicit_tag_and_constraints( + &mut self, + tag: Tag, + constraints: Constraints, + ) -> Result, Self::Error> + where + D: Decode, + { + self.decode_extension_addition_with_tag_and_constraints::(tag, constraints) + } - fn decode_extension_addition_with_constraints( + fn decode_extension_addition_with_tag_and_constraints( &mut self, + _tag: Tag, constraints: Constraints, ) -> Result, Self::Error> where diff --git a/src/oer/enc.rs b/src/oer/enc.rs index b26fbf84..5d936cfe 100644 --- a/src/oer/enc.rs +++ b/src/oer/enc.rs @@ -872,12 +872,9 @@ impl crate::Encoder for Encoder<'_> { tag: Tag, value: &V, ) -> Result { - if let Some((_, true)) = self.field_bitfield.get(&(self.current_field_index, tag)) { - value.encode(self) - } else if !self - .field_bitfield - .contains_key(&(self.current_field_index, tag)) - { + // Whether we have a choice type being encoded + if V::TAG == Tag::EOC { + self.set_bit(tag, true); value.encode(self) } else { self.set_bit(tag, true); diff --git a/src/per/de.rs b/src/per/de.rs index f2c2de76..41126419 100644 --- a/src/per/de.rs +++ b/src/per/de.rs @@ -880,9 +880,20 @@ impl crate::Decoder for Decoder<'_> { Ok(value) } + fn decode_optional_with_explicit_prefix( + &mut self, + tag: Tag, + ) -> Result, Self::Error> { + self.decode_optional_with_tag(tag) + } - fn decode_explicit_prefix(&mut self, _: Tag) -> Result { - D::decode(self) + fn decode_explicit_prefix(&mut self, tag: Tag) -> Result { + // Whether we have a choice here + if D::TAG == Tag::EOC { + D::decode(self) + } else { + D::decode_with_tag(self, tag) + } } fn decode_set( @@ -1066,8 +1077,20 @@ impl crate::Decoder for Decoder<'_> { D::decode(&mut decoder).map(Some) } - fn decode_extension_addition_with_constraints( + fn decode_extension_addition_with_explicit_tag_and_constraints( + &mut self, + tag: Tag, + constraints: Constraints, + ) -> core::result::Result, Self::Error> + where + D: Decode, + { + self.decode_extension_addition_with_tag_and_constraints::(tag, constraints) + } + + fn decode_extension_addition_with_tag_and_constraints( &mut self, + _: Tag, constraints: Constraints, ) -> core::result::Result, Self::Error> where diff --git a/src/per/enc.rs b/src/per/enc.rs index c1b14fb7..0472e8d3 100644 --- a/src/per/enc.rs +++ b/src/per/enc.rs @@ -1082,14 +1082,8 @@ impl crate::Encoder for Encoder { tag: Tag, value: &V, ) -> Result { - if let Some((_, true)) = self.field_bitfield.get(&(self.current_field_index, tag)) { - value.encode(self) - } else if !self - .field_bitfield - .contains_key(&(self.current_field_index, tag)) - { - // There is no bitfield if none of the parent objects is struct/set - // But we still need to handle nested choices explicitly + if V::TAG == Tag::EOC { + self.set_bit(tag, true)?; value.encode(self) } else { self.set_bit(tag, true)?;