Skip to content

Commit 21d4c6a

Browse files
committed
der: rename decode_with to peek_decode_optional
der: replace tag skip condition to `tag.number() != tag_number` der: add class param to peek_decode_optional
1 parent 937e611 commit 21d4c6a

File tree

1 file changed

+48
-43
lines changed

1 file changed

+48
-43
lines changed

der/src/asn1/context_specific.rs

+48-43
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Context-specific field.
22
33
use crate::{
4-
Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, EncodeValueRef, Error, Header,
4+
Choice, Class, Decode, DecodeValue, DerOrd, Encode, EncodeValue, EncodeValueRef, Error, Header,
55
Length, Reader, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer, asn1::AnyRef,
66
};
77
use core::cmp::Ordering;
@@ -46,7 +46,9 @@ impl<T> ContextSpecific<T> {
4646
where
4747
T: Decode<'a>,
4848
{
49-
Self::decode_with(reader, tag_number, |reader| Self::decode(reader))
49+
peek_decode_optional(reader, Class::ContextSpecific, tag_number, |reader| {
50+
Self::decode(reader)
51+
})
5052
}
5153

5254
/// Attempt to decode an `IMPLICIT` ASN.1 `CONTEXT-SPECIFIC` field with the
@@ -62,45 +64,50 @@ impl<T> ContextSpecific<T> {
6264
where
6365
T: DecodeValue<'a> + Tagged,
6466
{
65-
Self::decode_with::<_, _, T::Error>(reader, tag_number, |reader| {
66-
let header = Header::decode(reader)?;
67-
let value = T::decode_value(reader, header)?;
68-
69-
if header.tag.is_constructed() != value.tag().is_constructed() {
70-
return Err(header.tag.non_canonical_error().into());
71-
}
72-
73-
Ok(Self {
74-
tag_number,
75-
tag_mode: TagMode::Implicit,
76-
value,
77-
})
78-
})
67+
peek_decode_optional::<Self, _, _, T::Error>(
68+
reader,
69+
Class::ContextSpecific,
70+
tag_number,
71+
|reader| {
72+
let header = Header::decode(reader)?;
73+
let value = T::decode_value(reader, header)?;
74+
75+
if header.tag.is_constructed() != value.tag().is_constructed() {
76+
return Err(header.tag.non_canonical_error().into());
77+
}
78+
79+
Ok(Self {
80+
tag_number,
81+
tag_mode: TagMode::Implicit,
82+
value,
83+
})
84+
},
85+
)
7986
}
87+
}
8088

81-
/// Attempt to decode a context-specific field with the given
82-
/// helper callback.
83-
fn decode_with<'a, F, R: Reader<'a>, E>(
84-
reader: &mut R,
85-
tag_number: TagNumber,
86-
f: F,
87-
) -> Result<Option<Self>, E>
88-
where
89-
F: FnOnce(&mut R) -> Result<Self, E>,
90-
E: From<Error>,
91-
{
92-
while let Some(tag) = Tag::peek_optional(reader)? {
93-
if !tag.is_context_specific() || (tag.number() > tag_number) {
94-
break;
95-
} else if tag.number() == tag_number {
96-
return Some(f(reader)).transpose();
97-
} else {
98-
AnyRef::decode(reader)?;
99-
}
100-
}
101-
102-
Ok(None)
89+
/// Attempt to decode a context-specific (or any given class) field
90+
/// with the given helper callback.
91+
fn peek_decode_optional<'a, T, F, R: Reader<'a>, E>(
92+
reader: &mut R,
93+
class: Class,
94+
tag_number: TagNumber,
95+
f: F,
96+
) -> Result<Option<T>, E>
97+
where
98+
F: FnOnce(&mut R) -> Result<T, E>,
99+
E: From<Error>,
100+
{
101+
// Peek tag or ignore end of stream
102+
let Some(tag) = Tag::peek_optional(reader)? else {
103+
return Ok(None);
104+
};
105+
// Ignore tags with different numbers
106+
if tag.class() != class || tag.number() != tag_number {
107+
return Ok(None);
103108
}
109+
// Tag matches - callback reads tag and decodes value
110+
Some(f(reader)).transpose()
104111
}
105112

106113
impl<'a, T> Choice<'a> for ContextSpecific<T>
@@ -335,13 +342,11 @@ mod tests {
335342
}
336343

337344
#[test]
338-
fn context_specific_skipping_unknown_field() {
345+
fn context_specific_not_skipping_unknown_field() {
339346
let tag = TagNumber(1);
340347
let mut reader = SliceReader::new(&hex!("A003020100A103020101")).unwrap();
341-
let field = ContextSpecific::<u8>::decode_explicit(&mut reader, tag)
342-
.unwrap()
343-
.unwrap();
344-
assert_eq!(field.value, 1);
348+
let field = ContextSpecific::<u8>::decode_explicit(&mut reader, tag).unwrap();
349+
assert_eq!(field, None);
345350
}
346351

347352
#[test]

0 commit comments

Comments
 (0)