diff --git a/der/src/asn1/context_specific.rs b/der/src/asn1/context_specific.rs index e6a769d96..8a714d04a 100644 --- a/der/src/asn1/context_specific.rs +++ b/der/src/asn1/context_specific.rs @@ -22,7 +22,7 @@ pub fn decode_implicit<'a, R: Reader<'a>, T: Tagged + DecodeValue<'a>>( number: TagNumber, reader: &mut R, ) -> Result, T::Error> { - match AnyCustomClassImplicit::decode_implicit(Class::ContextSpecific, number, reader) { + match AnyCustomClassImplicit::decode_skipping(Class::ContextSpecific, number, reader) { Ok(Some(custom)) => Ok(Some(custom.value)), Ok(None) => Ok(None), Err(err) => Err(err), @@ -33,7 +33,7 @@ pub fn decode_explicit<'a, R: Reader<'a>, T: Decode<'a>>( number: TagNumber, reader: &mut R, ) -> Result, T::Error> { - match AnyCustomClassExplicit::decode_explicit(Class::ContextSpecific, number, reader) { + match AnyCustomClassExplicit::decode_skipping(Class::ContextSpecific, number, reader) { Ok(Some(custom)) => Ok(Some(custom.value)), Ok(None) => Ok(None), Err(err) => Err(err), diff --git a/der/src/asn1/custom_class.rs b/der/src/asn1/custom_class.rs index c21d56785..973856077 100644 --- a/der/src/asn1/custom_class.rs +++ b/der/src/asn1/custom_class.rs @@ -44,7 +44,7 @@ impl CustomClass { where T: Decode<'a>, { - match AnyCustomClassExplicit::decode_explicit(Class::from(CLASS), TagNumber(TAG), reader) { + match AnyCustomClassExplicit::decode_skipping(Class::from(CLASS), TagNumber(TAG), reader) { Ok(Some(custom)) => Ok(Some(Self { value: custom.value, })), @@ -70,21 +70,21 @@ fn is_unskippable_tag(tag: Tag, expected_class: Class, expected_number: TagNumbe /// Attempt to decode a custom class-tagged field with the given /// helper callback. -fn decode_with<'a, F, R: Reader<'a>, E, T>( +fn decode_peeking<'a, F, R: Reader<'a>, E, T>( reader: &mut R, expected_class: Class, expected_number: TagNumber, f: F, ) -> Result, E> where - F: FnOnce(Tag, &mut R) -> Result, + F: FnOnce(&mut R) -> Result, E: From, { while let Some(tag) = Tag::peek_optional(reader)? { if is_unskippable_tag(tag, expected_class, expected_number) { break; } else if tag.number() == expected_number { - return Some(f(tag, reader)).transpose(); + return Some(f(reader)).transpose(); } else { AnyRef::decode(reader)?; } @@ -104,7 +104,7 @@ impl CustomClassImplicit { where T: DecodeValue<'a> + Tagged, { - match AnyCustomClassImplicit::decode_implicit(Class::from(CLASS), TagNumber(TAG), reader) { + match AnyCustomClassImplicit::decode_skipping(Class::from(CLASS), TagNumber(TAG), reader) { Ok(Some(custom)) => Ok(Some(Self { value: custom.value, })), @@ -130,18 +130,33 @@ impl<'a, T> AnyCustomClassExplicit where T: Decode<'a>, { - pub fn decode_explicit>( + pub fn decode_skipping>( class: Class, number: TagNumber, reader: &mut R, ) -> Result, T::Error> { - decode_with(reader, class, number, |tag, reader| { + decode_peeking(reader, class, number, |reader| { + Self::decode(class, number, reader) + }) + } + + pub fn decode>( + class: Class, + number: TagNumber, + reader: &mut R, + ) -> Result { + let header = Header::decode(reader)?; + + if header.tag.class() == class { Ok(Self { - value: T::decode(reader)?, - tag_number: tag.number(), - constructed: tag.is_constructed(), + value: reader.read_nested(header.length, |reader| T::decode(reader))?, + tag_number: header.tag.number(), + constructed: header.tag.is_constructed(), }) - }) + } else { + let expected = expected_tag_constructed(class, number, true); + Err(header.tag.unexpected_error(Some(expected)).into()) + } } } @@ -149,12 +164,12 @@ impl<'a, T> AnyCustomClassImplicit where T: Tagged + DecodeValue<'a>, { - pub fn decode_implicit>( + pub fn decode_skipping>( class: Class, number: TagNumber, reader: &mut R, ) -> Result, T::Error> { - decode_with::<_, _, T::Error, _>(reader, class, number, |_tag, reader| { + decode_peeking::<_, _, T::Error, _>(reader, class, number, |reader| { let header = Header::decode(reader)?; let value = T::decode_value(reader, header)?; @@ -198,15 +213,11 @@ where type Error = T::Error; fn decode>(reader: &mut R) -> Result { - let header = Header::decode(reader)?; - - if header.tag.class() == Class::from(CLASS) { - Ok(Self { - value: reader.read_nested(header.length, |reader| T::decode(reader))?, - }) - } else { - let expected = expected_tag_constructed(Class::from(CLASS), TagNumber(TAG), true); - Err(header.tag.unexpected_error(Some(expected)).into()) + match AnyCustomClassExplicit::::decode(Class::from(CLASS), TagNumber(TAG), reader) { + Ok(custom) => Ok(Self { + value: custom.value, + }), + Err(err) => Err(err), } } } diff --git a/der/src/reader.rs b/der/src/reader.rs index 95e2445f0..b67779213 100644 --- a/der/src/reader.rs +++ b/der/src/reader.rs @@ -56,13 +56,13 @@ pub trait Reader<'r>: Sized { T: DecodeValue<'r> + FixedTag + 'r, { Ok(match tag_mode { - TagMode::Explicit => AnyCustomClassExplicit::::decode_explicit( + TagMode::Explicit => AnyCustomClassExplicit::::decode_skipping( Class::ContextSpecific, tag_number, self, )? .map(|field| field.value), - TagMode::Implicit => AnyCustomClassImplicit::::decode_implicit( + TagMode::Implicit => AnyCustomClassImplicit::::decode_skipping( Class::ContextSpecific, tag_number, self,