Skip to content

Commit f2625e7

Browse files
committed
der: initial Reader trait
Begins moving core decoding functionality into a `Reader` trait. The longer-term goal is to move enough functionality to the trait to support things like one-pass decoding directly from PEM for `DecodeOwned` types.
1 parent ad4a4fc commit f2625e7

17 files changed

Lines changed: 162 additions & 111 deletions

der/derive/src/choice.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ impl DeriveChoice {
9696

9797
impl<#lt_params> ::der::Decode<#lifetime> for #ident<#lt_params> {
9898
fn decode(decoder: &mut ::der::Decoder<#lifetime>) -> ::der::Result<Self> {
99+
use der::Reader as _;
99100
match decoder.peek_tag()? {
100101
#(#decode_body)*
101102
actual => Err(der::ErrorKind::TagUnexpected {

der/src/asn1/bit_string.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
asn1::Any, ByteSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Encoder, Error, ErrorKind,
5-
FixedTag, Header, Length, Result, Tag, ValueOrd, Writer,
5+
FixedTag, Header, Length, Reader, Result, Tag, ValueOrd, Writer,
66
};
77
use core::{cmp::Ordering, iter::FusedIterator};
88

@@ -122,7 +122,7 @@ impl<'a> DecodeValue<'a> for BitString<'a> {
122122
length: (header.length - Length::ONE)?,
123123
};
124124

125-
let unused_bits = decoder.byte()?;
125+
let unused_bits = decoder.read_byte()?;
126126
let inner = ByteSlice::decode_value(decoder, header)?;
127127
Self::new(unused_bits, inner.as_bytes())
128128
}

der/src/asn1/boolean.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
asn1::Any, ord::OrdIsValueOrd, ByteSlice, DecodeValue, Decoder, EncodeValue, Encoder, Error,
5-
ErrorKind, FixedTag, Header, Length, Result, Tag, Writer,
5+
ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, Writer,
66
};
77

88
/// Byte used to encode `true` in ASN.1 DER. From X.690 Section 11.1:
@@ -20,7 +20,7 @@ impl<'a> DecodeValue<'a> for bool {
2020
return Err(decoder.error(ErrorKind::Length { tag: Self::TAG }));
2121
}
2222

23-
match decoder.byte()? {
23+
match decoder.read_byte()? {
2424
FALSE_OCTET => Ok(false),
2525
TRUE_OCTET => Ok(true),
2626
_ => Err(Self::TAG.non_canonical_error()),

der/src/asn1/context_specific.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
asn1::Any, Choice, Decode, DecodeValue, Decoder, DerOrd, Encode, EncodeValue, EncodeValueRef,
5-
Encoder, Error, Header, Length, Result, Tag, TagMode, TagNumber, Tagged, ValueOrd,
5+
Encoder, Error, Header, Length, Reader, Result, Tag, TagMode, TagNumber, Tagged, ValueOrd,
66
};
77
use core::cmp::Ordering;
88

der/src/asn1/optional.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! ASN.1 `OPTIONAL` as mapped to Rust's `Option` type
22
3-
use crate::{Choice, Decode, Decoder, DerOrd, Encode, Encoder, Length, Result, Tag};
3+
use crate::{Choice, Decode, Decoder, DerOrd, Encode, Encoder, Length, Reader, Result, Tag};
44
use core::cmp::Ordering;
55

66
impl<'a, T> Decode<'a> for Option<T>

der/src/asn1/sequence.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use crate::{
55
ByteSlice, Decode, DecodeValue, Decoder, Encode, EncodeValue, Encoder, FixedTag, Header,
6-
Length, Result, Tag,
6+
Length, Reader, Result, Tag,
77
};
88

99
/// ASN.1 `SEQUENCE` trait.

der/src/asn1/sequence_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
arrayvec, ord::iter_cmp, ArrayVec, Decode, DecodeValue, Decoder, DerOrd, Encode, EncodeValue,
5-
Encoder, ErrorKind, FixedTag, Header, Length, Result, Tag, ValueOrd,
5+
Encoder, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd,
66
};
77
use core::cmp::Ordering;
88

der/src/asn1/set_of.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
arrayvec, ord::iter_cmp, ArrayVec, Decode, DecodeValue, Decoder, DerOrd, Encode, EncodeValue,
5-
Encoder, Error, ErrorKind, FixedTag, Header, Length, Result, Tag, ValueOrd,
5+
Encoder, Error, ErrorKind, FixedTag, Header, Length, Reader, Result, Tag, ValueOrd,
66
};
77
use core::cmp::Ordering;
88

der/src/byte_slice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
use crate::{
55
str_slice::StrSlice, DecodeValue, Decoder, DerOrd, EncodeValue, Encoder, Error, Header, Length,
6-
Result, Writer,
6+
Reader, Result, Writer,
77
};
88
use core::cmp::Ordering;
99

@@ -57,7 +57,7 @@ impl AsRef<[u8]> for ByteSlice<'_> {
5757

5858
impl<'a> DecodeValue<'a> for ByteSlice<'a> {
5959
fn decode_value(decoder: &mut Decoder<'a>, header: Header) -> Result<Self> {
60-
decoder.bytes(header.length).and_then(Self::new)
60+
decoder.read_slice(header.length).and_then(Self::new)
6161
}
6262
}
6363

der/src/decoder.rs

Lines changed: 52 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use crate::{
44
asn1::*, ByteSlice, Choice, Decode, DecodeValue, Encode, Error, ErrorKind, FixedTag, Header,
5-
Length, Result, Tag, TagMode, TagNumber,
5+
Length, Reader, Result, Tag, TagMode, TagNumber,
66
};
77

88
/// DER decoder.
@@ -74,46 +74,6 @@ impl<'a> Decoder<'a> {
7474
self.bytes.is_none()
7575
}
7676

77-
/// Get the position within the buffer.
78-
pub fn position(&self) -> Length {
79-
// TODO(tarcieri): avoid potential panic here
80-
(self.position + self.offset).expect("overflow")
81-
}
82-
83-
/// Peek at the next byte in the decoder without modifying the cursor.
84-
pub fn peek_byte(&self) -> Option<u8> {
85-
self.remaining()
86-
.ok()
87-
.and_then(|bytes| bytes.get(0).cloned())
88-
}
89-
90-
/// Peek at the next byte in the decoder and attempt to decode it as a
91-
/// [`Tag`] value.
92-
///
93-
/// Does not modify the decoder's state.
94-
pub fn peek_tag(&self) -> Result<Tag> {
95-
match self.peek_byte() {
96-
Some(byte) => byte.try_into(),
97-
None => {
98-
let actual_len = self.input_len()?;
99-
let expected_len = (actual_len + Length::ONE)?;
100-
Err(ErrorKind::Incomplete {
101-
expected_len,
102-
actual_len,
103-
}
104-
.into())
105-
}
106-
}
107-
}
108-
109-
/// Peek forward in the decoder, attempting to decode a [`Header`] from
110-
/// the data at the current position in the decoder.
111-
///
112-
/// Does not modify the decoder's state.
113-
pub fn peek_header(&self) -> Result<Header> {
114-
Header::decode(&mut self.clone())
115-
}
116-
11777
/// Finish decoding, returning the given value if there is no
11878
/// remaining data, or an error otherwise
11979
pub fn finish<T>(self, value: T) -> Result<T> {
@@ -130,14 +90,6 @@ impl<'a> Decoder<'a> {
13090
}
13191
}
13292

133-
/// Have we decoded all of the bytes in this [`Decoder`]?
134-
///
135-
/// Returns `false` if we're not finished decoding or if a fatal error
136-
/// has occurred.
137-
pub fn is_finished(&self) -> bool {
138-
self.remaining().map(|rem| rem.is_empty()).unwrap_or(false)
139-
}
140-
14193
/// Attempt to decode an ASN.1 `ANY` value.
14294
pub fn any(&mut self) -> Result<Any<'a>> {
14395
self.decode()
@@ -253,24 +205,58 @@ impl<'a> Decoder<'a> {
253205
SequenceRef::decode(self)?.decode_body(f)
254206
}
255207

256-
/// Decode a single byte, updating the internal cursor.
257-
pub(crate) fn byte(&mut self) -> Result<u8> {
258-
match self.bytes(1u8)? {
259-
[byte] => Ok(*byte),
260-
_ => {
208+
/// Obtain a slice of bytes contain a complete TLV production suitable for parsing later.
209+
pub fn tlv_bytes(&mut self) -> Result<&'a [u8]> {
210+
let header = self.peek_header()?;
211+
let header_len = header.encoded_len()?;
212+
self.read_slice((header_len + header.length)?)
213+
}
214+
215+
/// Obtain the remaining bytes in this decoder from the current cursor
216+
/// position.
217+
fn remaining(&self) -> Result<&'a [u8]> {
218+
let pos = usize::try_from(self.position)?;
219+
220+
match self.bytes.and_then(|slice| slice.as_bytes().get(pos..)) {
221+
Some(result) => Ok(result),
222+
None => {
261223
let actual_len = self.input_len()?;
262224
let expected_len = (actual_len + Length::ONE)?;
263-
Err(self.error(ErrorKind::Incomplete {
225+
Err(ErrorKind::Incomplete {
264226
expected_len,
265227
actual_len,
266-
}))
228+
}
229+
.at(self.position))
267230
}
268231
}
269232
}
233+
}
234+
235+
impl<'a> Reader<'a> for Decoder<'a> {
236+
fn input_len(&self) -> Result<Length> {
237+
Ok(self.bytes.ok_or(ErrorKind::Failed)?.len())
238+
}
239+
240+
fn peek_byte(&self) -> Option<u8> {
241+
self.remaining()
242+
.ok()
243+
.and_then(|bytes| bytes.get(0).cloned())
244+
}
245+
246+
fn peek_header(&self) -> Result<Header> {
247+
Header::decode(&mut self.clone())
248+
}
249+
250+
fn position(&self) -> Length {
251+
// TODO(tarcieri): avoid potential panic here
252+
(self.position + self.offset).expect("overflow")
253+
}
254+
255+
fn remaining_len(&self) -> Result<Length> {
256+
self.remaining()?.len().try_into()
257+
}
270258

271-
/// Obtain a slice of bytes of the given length from the current cursor
272-
/// position, or return an error if we have insufficient data.
273-
pub(crate) fn bytes(&mut self, len: impl TryInto<Length>) -> Result<&'a [u8]> {
259+
fn read_slice(&mut self, len: impl TryInto<Length>) -> Result<&'a [u8]> {
274260
if self.is_failed() {
275261
return Err(self.error(ErrorKind::Failed));
276262
}
@@ -295,38 +281,16 @@ impl<'a> Decoder<'a> {
295281
}
296282
}
297283

298-
/// Get the length of the input, if decoding hasn't failed.
299-
pub(crate) fn input_len(&self) -> Result<Length> {
300-
Ok(self.bytes.ok_or(ErrorKind::Failed)?.len())
301-
}
302-
303-
/// Obtain a slice of bytes contain a complete TLV production suitable for parsing later.
304-
pub fn tlv_bytes(&mut self) -> Result<&'a [u8]> {
305-
let header = self.peek_header()?;
306-
let header_len = header.encoded_len()?;
307-
self.bytes((header_len + header.length)?)
308-
}
309-
310-
/// Get the number of bytes still remaining in the buffer.
311-
pub(crate) fn remaining_len(&self) -> Result<Length> {
312-
self.remaining()?.len().try_into()
313-
}
314-
315-
/// Obtain the remaining bytes in this decoder from the current cursor
316-
/// position.
317-
fn remaining(&self) -> Result<&'a [u8]> {
318-
let pos = usize::try_from(self.position)?;
319-
320-
match self.bytes.and_then(|slice| slice.as_bytes().get(pos..)) {
321-
Some(result) => Ok(result),
322-
None => {
284+
fn read_byte(&mut self) -> Result<u8> {
285+
match self.read_slice(1u8)? {
286+
[byte] => Ok(*byte),
287+
_ => {
323288
let actual_len = self.input_len()?;
324289
let expected_len = (actual_len + Length::ONE)?;
325-
Err(ErrorKind::Incomplete {
290+
Err(self.error(ErrorKind::Incomplete {
326291
expected_len,
327292
actual_len,
328-
}
329-
.at(self.position))
293+
}))
330294
}
331295
}
332296
}
@@ -335,7 +299,7 @@ impl<'a> Decoder<'a> {
335299
#[cfg(test)]
336300
mod tests {
337301
use super::Decoder;
338-
use crate::{Decode, ErrorKind, Length, Tag};
302+
use crate::{Decode, ErrorKind, Length, Reader, Tag};
339303
use hex_literal::hex;
340304

341305
// INTEGER: 42

0 commit comments

Comments
 (0)