Skip to content

Commit 70a4f16

Browse files
committed
der: simplify Header::peek and Tag::peek
We can rely on the ability to clone the `Reader` to use the `Decode` implementation to implement peeking, so we don't need a separate bespoke implementation. This also avoids losing the `Reader` context while peeking.
1 parent 65b5d4c commit 70a4f16

File tree

3 files changed

+12
-49
lines changed

3 files changed

+12
-49
lines changed

der/src/asn1/optional.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,12 @@ where
1010
type Error = T::Error;
1111

1212
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Option<T>, Self::Error> {
13-
if let Some(tag) = Tag::peek_optional(reader)? {
14-
if T::can_decode(tag) {
15-
return T::decode(reader).map(Some);
16-
}
13+
if reader.is_finished() {
14+
return Ok(None);
15+
}
16+
17+
if T::can_decode(Tag::peek(reader)?) {
18+
return T::decode(reader).map(Some);
1719
}
1820

1921
Ok(None)

der/src/header.rs

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,6 @@ pub struct Header {
1414
}
1515

1616
impl Header {
17-
/// Maximum number of DER octets a header can be in this crate.
18-
pub(crate) const MAX_SIZE: usize = Tag::MAX_SIZE + Length::MAX_SIZE;
19-
2017
/// Create a new [`Header`] from a [`Tag`] and a specified length.
2118
///
2219
/// Returns an error if the length exceeds the limits of [`Length`].
@@ -29,17 +26,7 @@ impl Header {
2926
///
3027
/// Does not modify the reader's state.
3128
pub fn peek<'a>(reader: &impl Reader<'a>) -> Result<Self> {
32-
let mut buf = [0u8; Self::MAX_SIZE];
33-
34-
for i in 2..Self::MAX_SIZE {
35-
let slice = &mut buf[0..i];
36-
reader.peek_into(slice)?;
37-
if let Ok(header) = Self::from_der(slice) {
38-
return Ok(header);
39-
}
40-
}
41-
reader.peek_into(&mut buf[..])?;
42-
Self::from_der(&buf[..])
29+
Header::decode(&mut reader.clone())
4330
}
4431
}
4532

der/src/tag.rs

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -166,29 +166,7 @@ impl Tag {
166166
///
167167
/// Does not modify the reader's state.
168168
pub fn peek<'a>(reader: &impl Reader<'a>) -> Result<Self> {
169-
Self::peek_optional(reader)?.ok_or_else(|| Error::incomplete(reader.input_len()))
170-
}
171-
172-
pub(crate) fn peek_optional<'a>(reader: &impl Reader<'a>) -> Result<Option<Self>> {
173-
let mut buf = [0u8; Self::MAX_SIZE];
174-
if reader.peek_into(&mut buf[0..1]).is_err() {
175-
// Ignore empty buffer
176-
return Ok(None);
177-
}
178-
179-
if let Ok(tag) = Self::from_der(&buf[0..1]) {
180-
return Ok(Some(tag));
181-
}
182-
183-
for i in 2..=Self::MAX_SIZE {
184-
let slice = &mut buf[0..i];
185-
reader.peek_into(slice)?;
186-
187-
if let Ok(tag) = Self::from_der(slice) {
188-
return Ok(Some(tag));
189-
}
190-
}
191-
Err(ErrorKind::TagNumberInvalid.into())
169+
Self::decode(&mut reader.clone())
192170
}
193171

194172
/// Returns true if given context-specific (or any given class) tag number matches the peeked tag.
@@ -197,16 +175,12 @@ impl Tag {
197175
expected_class: Class,
198176
expected_tag_number: TagNumber,
199177
) -> Result<bool> {
200-
// Peek tag or ignore end of stream
201-
let Some(tag) = Tag::peek_optional(reader)? else {
202-
return Ok(false);
203-
};
204-
// Ignore tags with different numbers
205-
if tag.class() != expected_class || tag.number() != expected_tag_number {
178+
if reader.is_finished() {
206179
return Ok(false);
207180
}
208-
// Tag matches
209-
Ok(true)
181+
182+
let tag = Self::peek(reader)?;
183+
Ok(tag.class() == expected_class && tag.number() == expected_tag_number)
210184
}
211185

212186
/// Assert that this [`Tag`] matches the provided expected tag.

0 commit comments

Comments
 (0)