diff --git a/der/src/asn1/any.rs b/der/src/asn1/any.rs index 439240776..cde3ea606 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 8eb11165e..2695a9e1f 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`]. /// @@ -152,7 +163,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, @@ -189,10 +200,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 0ba035a44..0ffacc143 100644 --- a/der/src/decode.rs +++ b/der/src/decode.rs @@ -68,7 +68,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) } } @@ -130,6 +130,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 69b2e7362..3c4f7a39b 100644 --- a/der/src/reader.rs +++ b/der/src/reader.rs @@ -192,7 +192,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. @@ -214,7 +214,7 @@ where F: FnOnce(&mut R, Header) -> Result, { header.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. if header.length.is_indefinite() {