diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index 2646bc1d4..636300178 100644 --- a/der/src/asn1/any.rs +++ b/der/src/asn1/any.rs @@ -275,7 +275,7 @@ mod allocating { fn decode>(reader: &mut R) -> Result { let header = Header::decode(reader)?; - read_value(reader, header, Self::decode_value) + read_value(reader, header, Self::decode_value_nested) } } diff --git a/der/src/asn1/internal_macros.rs b/der/src/asn1/internal_macros.rs index 1d5c1c7a6..225a6b211 100644 --- a/der/src/asn1/internal_macros.rs +++ b/der/src/asn1/internal_macros.rs @@ -122,6 +122,17 @@ macro_rules! impl_custom_class { Ok(Some(Self::decode(reader)?)) } + /// Decode inner tag-length-value of `EXPLICIT` field. + fn decode_explicit_inner<'a, R: Reader<'a>>( + reader: &mut R, + header: Header + ) -> Result + where + T: Decode<'a> + { + reader.read_nested(header.length(), |r| T::decode(r)) + } + #[doc = concat!("Attempt to decode an `IMPLICIT` ASN.1 `", $asn1_class_name, "` field with the")] /// provided [`TagNumber`]. /// @@ -154,7 +165,7 @@ macro_rules! impl_custom_class { } // read_value checks if header matches decoded length - let value = crate::reader::read_value(reader, header, T::decode_value)?; + let value = crate::reader::read_value(reader, header, T::decode_value_nested)?; Ok(Some(Self { tag_number, @@ -191,10 +202,7 @@ macro_rules! impl_custom_class { Tag::$class_enum_name { number, .. } => Ok(Self { tag_number: number, tag_mode: TagMode::default(), - value: crate::reader::read_value(reader, header, |reader, _| { - // Decode inner tag-length-value of EXPLICIT - T::decode(reader) - })?, + value: crate::reader::read_value(reader, header, Self::decode_explicit_inner)?, }), tag => Err(reader.error(tag.unexpected_error(None)).into()) } diff --git a/der/src/decode.rs b/der/src/decode.rs index d82bfa9af..94cd46a9d 100644 --- a/der/src/decode.rs +++ b/der/src/decode.rs @@ -73,7 +73,7 @@ where fn decode>(reader: &mut R) -> Result>::Error> { let header = Header::decode(reader)?; header.tag().assert_eq(T::TAG)?; - read_value(reader, header, T::decode_value) + read_value(reader, header, T::decode_value_nested) } } @@ -135,6 +135,16 @@ pub trait DecodeValue<'a>: Sized { /// Attempt to decode this message using the provided [`Reader`]. fn decode_value>(reader: &mut R, header: Header) -> Result; + + /// Attempt to decode this message using the nested [`Reader`], using [`Reader::read_nested`] wrapper. + /// + /// For primitive types, this function can be overridden to [`DecodeValue::decode_value`] directly. + fn decode_value_nested>( + reader: &mut R, + header: Header, + ) -> Result { + reader.read_nested(header.length, |r| Self::decode_value(r, header)) + } } #[cfg(feature = "alloc")] diff --git a/der/src/reader.rs b/der/src/reader.rs index dc3c2e052..8fadb0575 100644 --- a/der/src/reader.rs +++ b/der/src/reader.rs @@ -195,7 +195,7 @@ pub trait Reader<'r>: Clone { { let header = Header::decode(self)?; header.tag().assert_eq(Tag::Sequence)?; - read_value(self, header, |r, _| f(r)) + read_value(self, header, |r, h| r.read_nested(h.length, |r| f(r))) } /// Obtain a slice of bytes containing a complete TLV production suitable for parsing later. @@ -219,7 +219,7 @@ where #[cfg(feature = "ber")] let header = header.with_length(header.length().sans_eoc()); - let ret = reader.read_nested(header.length(), |r| f(r, header))?; + let ret = f(reader, header)?; // Consume EOC marker if the length is indefinite. #[cfg(feature = "ber")]