Skip to content

Commit fd40fd7

Browse files
committed
der: use Reader<'a> as input for Decode::decode
Implements decoding generically in terms of the `Reader` trait, similar to what #611 did for encoding. This approach can enable 1-pass on-the-fly PEM decoding for `DecodeOwned` types (although that will require some additional work beyond what's in this PR).
1 parent 53e2304 commit fd40fd7

67 files changed

Lines changed: 790 additions & 781 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

der/derive/src/asn1_type.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,13 @@ impl Asn1Type {
4747
/// Get a `der::Decoder` object for a particular ASN.1 type
4848
pub fn decoder(self) -> TokenStream {
4949
match self {
50-
Asn1Type::BitString => quote!(decoder.bit_string()?),
51-
Asn1Type::Ia5String => quote!(decoder.ia5_string()?),
52-
Asn1Type::GeneralizedTime => quote!(decoder.generalized_time()?),
53-
Asn1Type::OctetString => quote!(decoder.octet_string()?),
54-
Asn1Type::PrintableString => quote!(decoder.printable_string()?),
55-
Asn1Type::UtcTime => quote!(decoder.utc_time()?),
56-
Asn1Type::Utf8String => quote!(decoder.utf8_string()?),
50+
Asn1Type::BitString => quote!(::der::asn1::BitString::decode(reader)?),
51+
Asn1Type::Ia5String => quote!(::der::asn1::Ia5String::decode(reader)?),
52+
Asn1Type::GeneralizedTime => quote!(::der::asn1::GeneralizedTime::decode(reader)?),
53+
Asn1Type::OctetString => quote!(::der::asn1::OctetString::decode(reader)?),
54+
Asn1Type::PrintableString => quote!(::der::asn1::PrintableString::decode(reader)?),
55+
Asn1Type::UtcTime => quote!(::der::asn1::UtcTime::decode(reader)?),
56+
Asn1Type::Utf8String => quote!(::der::asn1::Utf8String::decode(reader)?),
5757
}
5858
}
5959

der/derive/src/attributes.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ impl FieldAttrs {
9595
pub fn parse(attrs: &[Attribute], type_attrs: &TypeAttrs) -> Self {
9696
let mut asn1_type = None;
9797
let mut context_specific = None;
98-
9998
let mut default = None;
10099
let mut extensible = None;
101100
let mut optional = None;
@@ -203,13 +202,13 @@ impl FieldAttrs {
203202
if self.extensible || self.is_optional() {
204203
quote! {
205204
::der::asn1::ContextSpecific::<#type_params>::decode_explicit(
206-
decoder,
205+
reader,
207206
#tag_number
208207
)?
209208
}
210209
} else {
211210
quote! {
212-
match ::der::asn1::ContextSpecific::<#type_params>::decode(decoder)? {
211+
match ::der::asn1::ContextSpecific::<#type_params>::decode(reader)? {
213212
field if field.tag_number == #tag_number => Some(field),
214213
_ => None
215214
}
@@ -219,7 +218,7 @@ impl FieldAttrs {
219218
TagMode::Implicit => {
220219
quote! {
221220
::der::asn1::ContextSpecific::<#type_params>::decode_implicit(
222-
decoder,
221+
reader,
223222
#tag_number
224223
)?
225224
}
@@ -246,13 +245,15 @@ impl FieldAttrs {
246245
}
247246
} else if let Some(default) = &self.default {
248247
let type_params = self.asn1_type.map(|ty| ty.type_path()).unwrap_or_default();
249-
self.asn1_type.map(|ty| ty.decoder()).unwrap_or_else(
250-
|| quote!(decoder.decode::<Option<#type_params>>()?.unwrap_or_else(#default)),
251-
)
248+
self.asn1_type.map(|ty| ty.decoder()).unwrap_or_else(|| {
249+
quote! {
250+
Option::<#type_params>::decode(reader)?.unwrap_or_else(#default),
251+
}
252+
})
252253
} else {
253254
self.asn1_type
254255
.map(|ty| ty.decoder())
255-
.unwrap_or_else(|| quote!(decoder.decode()?))
256+
.unwrap_or_else(|| quote!(reader.decode()?))
256257
}
257258
}
258259

der/derive/src/choice.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
mod variant;
66

77
use self::variant::ChoiceVariant;
8-
use crate::TypeAttrs;
8+
use crate::{default_lifetime, TypeAttrs};
99
use proc_macro2::TokenStream;
1010
use proc_macro_error::abort;
1111
use quote::quote;
@@ -59,10 +59,9 @@ impl DeriveChoice {
5959
pub fn to_tokens(&self) -> TokenStream {
6060
let ident = &self.ident;
6161

62-
// Explicit lifetime or `'_`
6362
let lifetime = match self.lifetime {
6463
Some(ref lifetime) => quote!(#lifetime),
65-
None => quote!('_),
64+
None => default_lifetime(),
6665
};
6766

6867
// Lifetime parameters
@@ -88,16 +87,16 @@ impl DeriveChoice {
8887
}
8988

9089
quote! {
91-
impl<#lt_params> ::der::Choice<#lifetime> for #ident<#lt_params> {
90+
impl<#lifetime> ::der::Choice<#lifetime> for #ident<#lt_params> {
9291
fn can_decode(tag: ::der::Tag) -> bool {
9392
matches!(tag, #(#can_decode_body)|*)
9493
}
9594
}
9695

97-
impl<#lt_params> ::der::Decode<#lifetime> for #ident<#lt_params> {
98-
fn decode(decoder: &mut ::der::Decoder<#lifetime>) -> ::der::Result<Self> {
96+
impl<#lifetime> ::der::Decode<#lifetime> for #ident<#lt_params> {
97+
fn decode<R: ::der::Reader<#lifetime>>(reader: &mut R) -> ::der::Result<Self> {
9998
use der::Reader as _;
100-
match decoder.peek_tag()? {
99+
match reader.peek_tag()? {
101100
#(#decode_body)*
102101
actual => Err(der::ErrorKind::TagUnexpected {
103102
expected: None,

der/derive/src/choice/variant.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ mod tests {
169169
variant.to_decode_tokens().to_string(),
170170
quote! {
171171
::der::Tag::Utf8String => Ok(Self::ExampleVariant(
172-
decoder.decode()?
172+
reader.decode()?
173173
)),
174174
}
175175
.to_string()
@@ -214,7 +214,7 @@ mod tests {
214214
variant.to_decode_tokens().to_string(),
215215
quote! {
216216
::der::Tag::Utf8String => Ok(Self::ExampleVariant(
217-
decoder.utf8_string()?
217+
::der::asn1::Utf8String::decode(reader)?
218218
.try_into()?
219219
)),
220220
}
@@ -273,7 +273,7 @@ mod tests {
273273
constructed: #constructed,
274274
number: #tag_number,
275275
} => Ok(Self::ExplicitVariant(
276-
match ::der::asn1::ContextSpecific::<>::decode(decoder)? {
276+
match ::der::asn1::ContextSpecific::<>::decode(reader)? {
277277
field if field.tag_number == #tag_number => Some(field),
278278
_ => None
279279
}
@@ -359,7 +359,7 @@ mod tests {
359359
number: #tag_number,
360360
} => Ok(Self::ImplicitVariant(
361361
::der::asn1::ContextSpecific::<>::decode_implicit(
362-
decoder,
362+
reader,
363363
#tag_number
364364
)?
365365
.ok_or_else(|| {

der/derive/src/enumerated.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! the purposes of decoding/encoding ASN.1 `ENUMERATED` types as mapped to
33
//! enum variants.
44
5-
use crate::ATTR_NAME;
5+
use crate::{default_lifetime, ATTR_NAME};
66
use proc_macro2::TokenStream;
77
use proc_macro_error::abort;
88
use quote::quote;
@@ -102,6 +102,7 @@ impl DeriveEnumerated {
102102

103103
/// Lower the derived output into a [`TokenStream`].
104104
pub fn to_tokens(&self) -> TokenStream {
105+
let default_lifetime = default_lifetime();
105106
let ident = &self.ident;
106107
let repr = &self.repr;
107108
let tag = match self.integer {
@@ -115,12 +116,12 @@ impl DeriveEnumerated {
115116
}
116117

117118
quote! {
118-
impl ::der::DecodeValue<'_> for #ident {
119-
fn decode_value(
120-
decoder: &mut ::der::Decoder<'_>,
119+
impl<#default_lifetime> ::der::DecodeValue<#default_lifetime> for #ident {
120+
fn decode_value<R: ::der::Reader<#default_lifetime>>(
121+
reader: &mut R,
121122
header: ::der::Header
122123
) -> ::der::Result<Self> {
123-
<#repr as ::der::DecodeValue>::decode_value(decoder, header)?.try_into()
124+
<#repr as ::der::DecodeValue>::decode_value(reader, header)?.try_into()
124125
}
125126
}
126127

der/derive/src/lib.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,16 @@ use crate::{
134134
value_ord::DeriveValueOrd,
135135
};
136136
use proc_macro::TokenStream;
137+
use proc_macro2::Span;
137138
use proc_macro_error::proc_macro_error;
138-
use syn::{parse_macro_input, DeriveInput};
139+
use quote::quote;
140+
use syn::{parse_macro_input, DeriveInput, Lifetime};
141+
142+
/// Get the default lifetime.
143+
fn default_lifetime() -> proc_macro2::TokenStream {
144+
let lifetime = Lifetime::new("'__der_lifetime", Span::call_site());
145+
quote!(#lifetime)
146+
}
139147

140148
/// Derive the [`Choice`][1] trait on an `enum`.
141149
///

der/derive/src/sequence.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
44
mod field;
55

6-
use crate::TypeAttrs;
6+
use crate::{default_lifetime, TypeAttrs};
77
use field::SequenceField;
88
use proc_macro2::TokenStream;
99
use proc_macro_error::abort;
@@ -59,10 +59,9 @@ impl DeriveSequence {
5959
pub fn to_tokens(&self) -> TokenStream {
6060
let ident = &self.ident;
6161

62-
// Explicit lifetime or `'_`
6362
let lifetime = match self.lifetime {
6463
Some(ref lifetime) => quote!(#lifetime),
65-
None => quote!('_),
64+
None => default_lifetime(),
6665
};
6766

6867
// Lifetime parameters
@@ -84,13 +83,14 @@ impl DeriveSequence {
8483
}
8584

8685
quote! {
87-
impl<#lt_params> ::der::DecodeValue<#lifetime> for #ident<#lt_params> {
88-
fn decode_value(
89-
decoder: &mut ::der::Decoder<#lifetime>,
86+
impl<#lifetime> ::der::DecodeValue<#lifetime> for #ident<#lt_params> {
87+
fn decode_value<R: ::der::Reader<#lifetime>>(
88+
reader: &mut R,
9089
header: ::der::Header,
9190
) -> ::der::Result<Self> {
92-
use ::der::DecodeValue;
93-
::der::asn1::SequenceRef::decode_value(decoder, header)?.decode_body(|decoder| {
91+
use ::der::{Decode as _, DecodeValue as _, Reader as _};
92+
93+
reader.read_nested(header.length, |reader| {
9494
#(#decode_body)*
9595

9696
Ok(Self {
@@ -100,7 +100,7 @@ impl DeriveSequence {
100100
}
101101
}
102102

103-
impl<#lt_params> ::der::Sequence<#lifetime> for #ident<#lt_params> {
103+
impl<#lifetime> ::der::Sequence<#lifetime> for #ident<#lt_params> {
104104
fn fields<F, T>(&self, f: F) -> ::der::Result<T>
105105
where
106106
F: FnOnce(&[&dyn der::Encode]) -> ::der::Result<T>,

der/derive/src/sequence/field.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,8 +146,8 @@ impl LowerFieldDecoder {
146146
/// Handle default value for a type.
147147
fn apply_default(&mut self, default: &Path, field_type: &Type) {
148148
self.decoder = quote! {
149-
decoder.decode::<Option<#field_type>>()?.unwrap_or_else(#default);
150-
}
149+
Option::<#field_type>::decode(reader)?.unwrap_or_else(#default);
150+
};
151151
}
152152
}
153153

@@ -287,7 +287,7 @@ mod tests {
287287
assert_eq!(
288288
field.to_decode_tokens().to_string(),
289289
quote! {
290-
let example_field = decoder.decode()?;
290+
let example_field = reader.decode()?;
291291
}
292292
.to_string()
293293
);
@@ -328,7 +328,7 @@ mod tests {
328328
field.to_decode_tokens().to_string(),
329329
quote! {
330330
let implicit_field = ::der::asn1::ContextSpecific::<>::decode_implicit(
331-
decoder,
331+
reader,
332332
::der::TagNumber::N0
333333
)?
334334
.ok_or_else(|| {

der/src/arrayvec.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,22 +66,9 @@ impl<T, const N: usize> ArrayVec<T, N> {
6666
self.length.checked_sub(1).and_then(|n| self.get(n))
6767
}
6868

69-
/// Try to convert this [`ArrayVec`] into a `[T; N]`.
70-
///
71-
/// Returns `None` if the [`ArrayVec`] does not contain `N` elements.
72-
pub fn try_into_array(self) -> Result<[T; N]> {
73-
if self.length != N {
74-
return Err(ErrorKind::Incomplete {
75-
expected_len: N.try_into()?,
76-
actual_len: self.length.try_into()?,
77-
}
78-
.into());
79-
}
80-
81-
Ok(self.elements.map(|elem| match elem {
82-
Some(e) => e,
83-
None => unreachable!(),
84-
}))
69+
/// Extract the inner array.
70+
pub fn into_array(self) -> [Option<T>; N] {
71+
self.elements
8572
}
8673
}
8774

der/src/asn1/any.rs

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

@@ -153,11 +153,12 @@ impl<'a> Choice<'a> for Any<'a> {
153153
}
154154

155155
impl<'a> Decode<'a> for Any<'a> {
156-
fn decode(decoder: &mut Decoder<'a>) -> Result<Any<'a>> {
157-
let header = Header::decode(decoder)?;
156+
fn decode<R: Reader<'a>>(reader: &mut R) -> Result<Any<'a>> {
157+
let header = Header::decode(reader)?;
158+
158159
Ok(Self {
159160
tag: header.tag,
160-
value: ByteSlice::decode_value(decoder, header)?,
161+
value: ByteSlice::decode_value(reader, header)?,
161162
})
162163
}
163164
}

0 commit comments

Comments
 (0)