Skip to content

Commit dc2e67f

Browse files
committed
feat: add decode_implicit and decode_explicit back
1 parent 7ce6ee5 commit dc2e67f

File tree

8 files changed

+134
-59
lines changed

8 files changed

+134
-59
lines changed

der/src/asn1.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ mod bmp_string;
1111
mod boolean;
1212
mod choice;
1313
mod context_specific;
14+
mod custom_class;
1415
mod generalized_time;
1516
mod ia5_string;
1617
mod integer;
@@ -30,22 +31,22 @@ mod teletex_string;
3031
mod utc_time;
3132
mod utf8_string;
3233
mod videotex_string;
33-
mod custom_class;
3434

3535
pub use self::{
3636
any::AnyRef,
3737
bit_string::{BitStringIter, BitStringRef},
3838
choice::Choice,
3939
//context_specific::{ContextSpecific, ContextSpecificRef},
40-
context_specific::{ContextSpecific},
40+
context_specific::ContextSpecific,
41+
custom_class::{AnyCustomClassExplicit, AnyCustomClassImplicit},
4142
generalized_time::GeneralizedTime,
4243
ia5_string::Ia5StringRef,
4344
integer::{int::IntRef, uint::UintRef},
4445
null::Null,
4546
octet_string::OctetStringRef,
4647
printable_string::PrintableStringRef,
4748
//private::{Private, PrivateRef},
48-
private::{Private},
49+
private::Private,
4950
sequence::{Sequence, SequenceRef},
5051
sequence_of::{SequenceOf, SequenceOfIter},
5152
set_of::{SetOf, SetOfIter},

der/src/asn1/context_specific.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use crate::{
77
};
88
use core::cmp::Ordering;
99

10-
use super::custom_class::{self, CustomClass, CustomClassImplicit};
10+
use super::custom_class::{
11+
self, AnyCustomClassExplicit, AnyCustomClassImplicit, CustomClass, CustomClassImplicit,
12+
};
1113

1214
/// Context-specific class, EXPLICIT
1315
pub type ContextSpecific<const TAG: u16, T> = CustomClass<T, TAG, CLASS_CONTEXT_SPECIFIC>;
@@ -20,8 +22,24 @@ pub fn decode_implicit<'a, R: Reader<'a>, T: Tagged + DecodeValue<'a>>(
2022
number: TagNumber,
2123
reader: &mut R,
2224
) -> Result<Option<T>, T::Error> {
23-
custom_class::decode_implicit(Class::ContextSpecific, number, reader)
25+
match AnyCustomClassImplicit::decode_implicit(Class::ContextSpecific, number, reader) {
26+
Ok(Some(custom)) => Ok(Some(custom.value)),
27+
Ok(None) => Ok(None),
28+
Err(err) => Err(err),
29+
}
2430
}
31+
32+
pub fn decode_explicit<'a, R: Reader<'a>, T: Decode<'a>>(
33+
number: TagNumber,
34+
reader: &mut R,
35+
) -> Result<Option<T>, T::Error> {
36+
match AnyCustomClassExplicit::decode_explicit(Class::ContextSpecific, number, reader) {
37+
Ok(Some(custom)) => Ok(Some(custom.value)),
38+
Ok(None) => Ok(None),
39+
Err(err) => Err(err),
40+
}
41+
}
42+
2543
// /// Context-specific field which wraps an owned inner value.
2644
// ///
2745
// /// This type decodes/encodes a field which is specific to a particular context

der/src/asn1/custom_class.rs

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use core::cmp::Ordering;
2+
use core::num;
23

34
use super::{AnyRef, Choice};
45
use crate::encode::Encode;
56
use crate::{
67
Class, Decode, DecodeValue, DerOrd, EncodeValue, Error, FixedTag, Header, Length, Reader,
7-
SliceReader, Tag, TagNumber, Tagged, ValueOrd, Writer,
8+
SliceReader, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer,
89
};
910

1011
/// Application, Context-specific or Private class field which wraps an owned inner value.
@@ -43,9 +44,13 @@ impl<T, const TAG: u16, const CLASS: u8> CustomClass<T, TAG, CLASS> {
4344
where
4445
T: Decode<'a>,
4546
{
46-
decode_with(reader, Class::from(CLASS), TagNumber(TAG), |reader| {
47-
Self::decode(reader)
48-
})
47+
match AnyCustomClassExplicit::decode_explicit(Class::from(CLASS), TagNumber(TAG), reader) {
48+
Ok(Some(custom)) => Ok(Some(Self {
49+
value: custom.value,
50+
})),
51+
Ok(None) => Ok(None),
52+
Err(err) => Err(err),
53+
}
4954
}
5055
}
5156

@@ -72,14 +77,14 @@ fn decode_with<'a, F, R: Reader<'a>, E, T>(
7277
f: F,
7378
) -> Result<Option<T>, E>
7479
where
75-
F: FnOnce(&mut R) -> Result<T, E>,
80+
F: FnOnce(Tag, &mut R) -> Result<T, E>,
7681
E: From<Error>,
7782
{
7883
while let Some(tag) = Tag::peek_optional(reader)? {
7984
if is_unskippable_tag(tag, expected_class, expected_number) {
8085
break;
8186
} else if tag.number() == expected_number {
82-
return Some(f(reader)).transpose();
87+
return Some(f(tag, reader)).transpose();
8388
} else {
8489
AnyRef::decode(reader)?;
8590
}
@@ -99,29 +104,71 @@ impl<T, const TAG: u16, const CLASS: u8> CustomClassImplicit<T, TAG, CLASS> {
99104
where
100105
T: DecodeValue<'a> + Tagged,
101106
{
102-
match decode_implicit(Class::from(CLASS), TagNumber(TAG), reader) {
103-
Ok(Some(value)) => Ok(Some(Self { value })),
107+
match AnyCustomClassImplicit::decode_implicit(Class::from(CLASS), TagNumber(TAG), reader) {
108+
Ok(Some(custom)) => Ok(Some(Self {
109+
value: custom.value,
110+
})),
104111
Ok(None) => Ok(None),
105112
Err(err) => Err(err),
106113
}
107114
}
108115
}
109116

110-
pub fn decode_implicit<'a, R: Reader<'a>, T: Tagged + DecodeValue<'a>>(
111-
class: Class,
112-
number: TagNumber,
113-
reader: &mut R,
114-
) -> Result<Option<T>, T::Error> {
115-
decode_with::<_, _, T::Error, _>(reader, class, number, |reader| {
116-
let header = Header::decode(reader)?;
117-
let value = T::decode_value(reader, header)?;
117+
pub struct AnyCustomClassExplicit<T> {
118+
pub tag_number: TagNumber,
119+
pub constructed: bool,
120+
pub value: T,
121+
}
118122

119-
if header.tag.is_constructed() != value.tag().is_constructed() {
120-
return Err(header.tag.non_canonical_error().into());
121-
}
123+
pub struct AnyCustomClassImplicit<T> {
124+
pub tag_number: TagNumber,
125+
pub constructed: bool,
126+
pub value: T,
127+
}
122128

123-
Ok(value)
124-
})
129+
impl<'a, T> AnyCustomClassExplicit<T>
130+
where
131+
T: Decode<'a>,
132+
{
133+
pub fn decode_explicit<R: Reader<'a>>(
134+
class: Class,
135+
number: TagNumber,
136+
reader: &mut R,
137+
) -> Result<Option<Self>, T::Error> {
138+
decode_with(reader, class, number, |tag, reader| {
139+
Ok(Self {
140+
value: T::decode(reader)?,
141+
tag_number: tag.number(),
142+
constructed: tag.is_constructed(),
143+
})
144+
})
145+
}
146+
}
147+
148+
impl<'a, T> AnyCustomClassImplicit<T>
149+
where
150+
T: Tagged + DecodeValue<'a>,
151+
{
152+
pub fn decode_implicit<R: Reader<'a>>(
153+
class: Class,
154+
number: TagNumber,
155+
reader: &mut R,
156+
) -> Result<Option<Self>, T::Error> {
157+
decode_with::<_, _, T::Error, _>(reader, class, number, |_tag, reader| {
158+
let header = Header::decode(reader)?;
159+
let value = T::decode_value(reader, header)?;
160+
161+
if header.tag.is_constructed() != value.tag().is_constructed() {
162+
return Err(header.tag.non_canonical_error().into());
163+
}
164+
165+
Ok(Self {
166+
tag_number: header.tag.number(),
167+
constructed: header.tag.is_constructed(),
168+
value,
169+
})
170+
})
171+
}
125172
}
126173

127174
impl<'a, T, const TAG: u16, const CLASS: u8> Choice<'a> for CustomClass<T, TAG, CLASS>

der/src/asn1/private.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,27 @@
11
//! Private field.
22
33
use crate::tag::{CLASS_APPLICATION, CLASS_CONTEXT_SPECIFIC, CLASS_PRIVATE};
4-
use crate::{Class, FixedTag};
54
use crate::{
65
asn1::AnyRef, Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, EncodeValueRef, Error,
76
Header, Length, Reader, SliceReader, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer,
87
};
8+
use crate::{Class, FixedTag};
99
use core::cmp::Ordering;
1010

1111
use super::custom_class::{CustomClass, CustomClassImplicit};
1212

1313
/// Application class, EXPLICIT
1414
pub type Application<const TAG: u16, T> = CustomClass<T, TAG, CLASS_APPLICATION>;
1515

16-
17-
1816
/// Private class, EXPLICIT
1917
pub type Private<const TAG: u16, T> = CustomClass<T, TAG, CLASS_PRIVATE>;
2018

2119
/// Application class, IMPLICIT
2220
pub type ApplicationImplicit<const TAG: u16, T> = CustomClassImplicit<T, TAG, CLASS_APPLICATION>;
2321

24-
2522
/// Private class, IMPLICIT
2623
pub type PrivateImplicit<const TAG: u16, T> = CustomClassImplicit<T, TAG, CLASS_PRIVATE>;
2724

28-
2925
// /// Private field reference.
3026
// ///
3127
// /// This type encodes a field which is whose meaning is specific to a given
@@ -145,8 +141,7 @@ mod tests {
145141
#[test]
146142
fn private_not_skipping_unknown_field() {
147143
let mut reader = SliceReader::new(&hex!("E003020100E103020101")).unwrap();
148-
let field = Private::<1, u8>::decode_optional(&mut reader)
149-
.unwrap();
144+
let field = Private::<1, u8>::decode_optional(&mut reader).unwrap();
150145
assert_eq!(field, None);
151146
}
152147

der/src/reader.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ pub(crate) mod pem;
55
pub(crate) mod slice;
66

77
use crate::{
8-
asn1::ContextSpecific, Decode, DecodeValue, Encode, EncodingRules, Error, ErrorKind, FixedTag,
9-
Header, Length, Tag, TagMode, TagNumber,
8+
asn1::{AnyCustomClassExplicit, AnyCustomClassImplicit, ContextSpecific},
9+
Class, Decode, DecodeValue, Encode, EncodingRules, Error, ErrorKind, FixedTag, Header, Length,
10+
Tag, TagMode, TagNumber,
1011
};
1112

1213
#[cfg(feature = "alloc")]
@@ -55,10 +56,19 @@ pub trait Reader<'r>: Sized {
5556
T: DecodeValue<'r> + FixedTag + 'r,
5657
{
5758
Ok(match tag_mode {
58-
TagMode::Explicit => ContextSpecific::<T>::decode_explicit(self, tag_number)?,
59-
TagMode::Implicit => decode_implicit(tag_number, self)?,
60-
}
61-
.map(|field| field.value))
59+
TagMode::Explicit => AnyCustomClassExplicit::<T>::decode_explicit(
60+
Class::ContextSpecific,
61+
tag_number,
62+
self,
63+
)?
64+
.map(|field| field.value),
65+
TagMode::Implicit => AnyCustomClassImplicit::<T>::decode_implicit(
66+
Class::ContextSpecific,
67+
tag_number,
68+
self,
69+
)?
70+
.map(|field| field.value),
71+
})
6272
}
6373

6474
/// Decode a value which impls the [`Decode`] trait.

der/src/tag.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ mod mode;
66
mod number;
77

88
pub use self::{class::Class, mode::TagMode, number::TagNumber};
9-
pub use self::{class::CLASS_UNIVERSAL, class::CLASS_CONTEXT_SPECIFIC, class::CLASS_APPLICATION, class::CLASS_PRIVATE};
9+
pub use self::{
10+
class::CLASS_APPLICATION, class::CLASS_CONTEXT_SPECIFIC, class::CLASS_PRIVATE,
11+
class::CLASS_UNIVERSAL,
12+
};
1013

1114
use crate::{Decode, DerOrd, Encode, Error, ErrorKind, Length, Reader, Result, Writer};
1215
use core::{cmp::Ordering, fmt};

der/src/tag/class.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ impl From<u8> for Class {
4141
0b01 => Class::Application,
4242
0b10 => Class::ContextSpecific,
4343
0b11 => Class::Private,
44-
_ => unreachable!()
44+
_ => unreachable!(),
4545
}
4646
}
4747
}
@@ -62,4 +62,4 @@ impl Class {
6262
pub const fn bits(&self) -> u8 {
6363
*self as u8
6464
}
65-
}
65+
}

der/src/writer/slice.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -66,23 +66,24 @@ impl<'a> SliceWriter<'a> {
6666
.ok_or_else(|| ErrorKind::Overlength.at(position))
6767
}
6868

69-
/// Encode a `CONTEXT-SPECIFIC` field with the provided tag number and mode.
70-
pub fn context_specific<T>(
71-
&mut self,
72-
tag_number: TagNumber,
73-
tag_mode: TagMode,
74-
value: &T,
75-
) -> Result<()>
76-
where
77-
T: EncodeValue + Tagged,
78-
{
79-
ContextSpecificRef {
80-
tag_number,
81-
tag_mode,
82-
value,
83-
}
84-
.encode(self)
85-
}
69+
// TODO
70+
// /// Encode a `CONTEXT-SPECIFIC` field with the provided tag number and mode.
71+
// pub fn context_specific<T>(
72+
// &mut self,
73+
// tag_number: TagNumber,
74+
// tag_mode: TagMode,
75+
// value: &T,
76+
// ) -> Result<()>
77+
// where
78+
// T: EncodeValue + Tagged,
79+
// {
80+
// ContextSpecificRef {
81+
// tag_number,
82+
// tag_mode,
83+
// value,
84+
// }
85+
// .encode(self)
86+
// }
8687

8788
/// Encode an ASN.1 `SEQUENCE` of the given length.
8889
///

0 commit comments

Comments
 (0)