Skip to content

Commit 5115c1a

Browse files
committed
der: add IsConstructed trait, impl'ed on any FixedTag
der_derive: impl IsConstructed on derive(Choice) der: draft of test for IsConstructed vs Tagged edge case der: test: generic CHOICE inside [0] IMPLICIT CHOICE Revert "der: test: generic CHOICE inside [0] IMPLICIT CHOICE" This reverts commit dda1215. Revert "der: draft of test for IsConstructed vs Tagged edge case" This reverts commit 5daa9ba. der: add IsConstructed test docs der: format tests simplify IsConstructed test
1 parent 8364eb5 commit 5115c1a

File tree

5 files changed

+43
-5
lines changed

5 files changed

+43
-5
lines changed

der/src/asn1/context_specific.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use crate::{
44
Choice, Decode, DecodeValue, DerOrd, Encode, EncodeValue, EncodeValueRef, Error, Header,
55
Length, Reader, Tag, TagMode, TagNumber, Tagged, ValueOrd, Writer, asn1::AnyRef,
6+
tag::IsConstructed,
67
};
78
use core::cmp::Ordering;
89

@@ -60,7 +61,7 @@ impl<T> ContextSpecific<T> {
6061
tag_number: TagNumber,
6162
) -> Result<Option<Self>, T::Error>
6263
where
63-
T: DecodeValue<'a> + Tagged,
64+
T: DecodeValue<'a> + IsConstructed,
6465
{
6566
Self::decode_with::<_, _, T::Error>(reader, tag_number, |reader| {
6667
// Decode IMPLICIT header
@@ -72,7 +73,7 @@ impl<T> ContextSpecific<T> {
7273
T::decode_value(reader, header)
7374
})?;
7475

75-
if header.tag.is_constructed() != value.tag().is_constructed() {
76+
if header.tag.is_constructed() != T::CONSTRUCTED {
7677
return Err(header.tag.non_canonical_error().into());
7778
}
7879

der/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,7 @@ pub use crate::{
377377
length::{IndefiniteLength, Length},
378378
ord::{DerOrd, ValueOrd},
379379
reader::{Reader, slice::SliceReader},
380-
tag::{Class, FixedTag, Tag, TagMode, TagNumber, Tagged},
380+
tag::{Class, FixedTag, IsConstructed, Tag, TagMode, TagNumber, Tagged},
381381
writer::{Writer, slice::SliceWriter},
382382
};
383383

der/src/tag.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,17 @@ impl<T: FixedTag + ?Sized> Tagged for T {
3232
}
3333
}
3434

35+
/// Types which have a constant ASN.1 constructed bit.
36+
pub trait IsConstructed {
37+
/// ASN.1 constructed bit
38+
const CONSTRUCTED: bool;
39+
}
40+
41+
/// Types which are [`FixedTag`] always known if they are constructed (or primitive).
42+
impl<T: FixedTag + ?Sized> IsConstructed for T {
43+
const CONSTRUCTED: bool = T::TAG.is_constructed();
44+
}
45+
3546
/// ASN.1 tags.
3647
///
3748
/// Tags are the leading identifier octet of the Tag-Length-Value encoding
@@ -229,7 +240,7 @@ impl Tag {
229240
}
230241

231242
/// Does this tag represent a constructed (as opposed to primitive) field?
232-
pub fn is_constructed(self) -> bool {
243+
pub const fn is_constructed(self) -> bool {
233244
match self {
234245
Tag::Sequence | Tag::Set => true,
235246
Tag::Application { constructed, .. }

der/tests/derive.rs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ mod choice {
112112
/// `Choice` with `IMPLICIT` tagging.
113113
mod implicit {
114114
use der::{
115-
Choice, Decode, Encode, SliceWriter,
115+
Choice, Decode, Encode, Sequence, SliceWriter,
116116
asn1::{BitStringRef, GeneralizedTime},
117117
};
118118
use hex_literal::hex;
@@ -179,6 +179,13 @@ mod choice {
179179
cs_time.encode(&mut encoder).unwrap();
180180
assert_eq!(TIME_DER, encoder.finish().unwrap());
181181
}
182+
183+
/// Test case for `CHOICE` inside `[0]` `EXPLICIT` tag in `SEQUENCE`.
184+
#[derive(Sequence, Debug, Eq, PartialEq)]
185+
pub struct ExplicitChoiceInsideSequence<'a> {
186+
#[asn1(tag_mode = "EXPLICIT", context_specific = "0")]
187+
choice_field: ImplicitChoice<'a>,
188+
}
182189
}
183190
}
184191

@@ -743,6 +750,21 @@ mod decode_value {
743750
}
744751
}
745752

753+
/// Custom derive test cases for the `DecodeValue` + `EncodeValue` macro combo.
754+
mod decode_encode_value {
755+
use der::{DecodeValue, EncodeValue, IsConstructed};
756+
757+
/// Example of a structure, that does not have a tag and is not a sequence
758+
/// but can be encoded as `[0] IMPLICIT`
759+
#[derive(DecodeValue, EncodeValue, Default, Eq, PartialEq, Debug)]
760+
struct DecodeEncodeCheck {
761+
field: bool,
762+
}
763+
impl IsConstructed for DecodeEncodeCheck {
764+
const CONSTRUCTED: bool = true;
765+
}
766+
}
767+
746768
/// Custom derive test cases for the `BitString` macro.
747769
#[cfg(feature = "std")]
748770
mod bitstring {

der_derive/src/choice.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ impl DeriveChoice {
9797
}
9898
}
9999

100+
impl #impl_generics ::der::IsConstructed for #ident #ty_generics #where_clause {
101+
const CONSTRUCTED: bool = true;
102+
}
103+
100104
impl #impl_generics ::der::Decode<#lifetime> for #ident #ty_generics #where_clause {
101105
type Error = #error;
102106

0 commit comments

Comments
 (0)