Skip to content

Commit 64fcb37

Browse files
authored
Fixes #418. Add support for explict tags and default values to encode correctly (#419)
1 parent 6250605 commit 64fcb37

File tree

3 files changed

+70
-2
lines changed

3 files changed

+70
-2
lines changed

macros/macros_impl/src/config.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -857,8 +857,13 @@ impl<'a> FieldConfig<'a> {
857857

858858
let encode = if self.tag.is_some() || self.container_config.automatic_tags {
859859
if self.tag.as_ref().is_some_and(|tag| tag.is_explicit()) {
860-
// Note: encoder must be aware if the field is optional and present, so we should not do the presence check on this level
861-
quote!(encoder.encode_explicit_prefix(#tag, &self.#field, #identifier)?;)
860+
if self.default.is_some() {
861+
// Note: encoder must be aware if the field is optional and present, so we should not do the presence check on this level
862+
quote!(encoder.encode_default_with_explicit_prefix(#tag, &self.#field, #default_fn #identifier)?;)
863+
} else {
864+
// Note: encoder must be aware if the field is optional and present, so we should not do the presence check on this level
865+
quote!(encoder.encode_explicit_prefix(#tag, &self.#field, #identifier)?;)
866+
}
862867
} else if self.extension_addition {
863868
quote!(
864869
#constraint_def

src/enc.rs

+14
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,20 @@ pub trait Encoder<'encoder, const RCL: usize = 0, const ECL: usize = 0> {
455455
}
456456
}
457457

458+
/// Encode the preset value of an optional field using Explicit Tags
459+
fn encode_default_with_explicit_prefix<E: Encode + PartialEq>(
460+
&mut self,
461+
tag: Tag,
462+
value: &E,
463+
default: impl FnOnce() -> E,
464+
identifier: Identifier,
465+
) -> Result<Self::Ok, Self::Error> {
466+
match (*value != (default)()).then_some(value) {
467+
Some(value) => self.encode_explicit_prefix(tag, value, identifier),
468+
None => self.encode_none_with_tag(tag, identifier),
469+
}
470+
}
471+
458472
/// Encode the present value of an optional field.
459473
fn encode_default_with_tag_and_constraints<E: Encode + PartialEq>(
460474
&mut self,

tests/explicit.rs

+49
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,23 @@ pub struct Sequence {
99
b: bool,
1010
}
1111

12+
#[derive(AsnType, Decode, Debug, Encode, PartialEq)]
13+
pub struct SequenceWithDefault {
14+
#[rasn(tag(explicit(application, 1)), default = "default_bool")]
15+
b: bool,
16+
}
17+
18+
#[derive(AsnType, Decode, Debug, Encode, PartialEq)]
19+
pub struct SequenceWithMultiDefault {
20+
#[rasn(tag(explicit(application, 1)), default = "default_bool")]
21+
b: bool,
22+
#[rasn(tag(explicit(application, 2)), default = "default_bool")]
23+
b2: bool,
24+
}
25+
pub fn default_bool() -> bool {
26+
true
27+
}
28+
1229
#[derive(AsnType, Decode, Debug, Encode, PartialEq)]
1330
#[rasn(tag(explicit(application, 1)))]
1431
pub struct InlineSequence {
@@ -67,6 +84,18 @@ const _: () = assert!(Tag::const_eq(DelegateSequence::TAG, &InlineSet::TAG,));
6784
#[test]
6885
fn works() {
6986
const EXPECTED: &[u8] = &[0x61, 0x5, 0x30, 0x3, 0x01, 0x1, 0xFF];
87+
// Note that the explicitly tagged field is dropped.
88+
// This makes it a sequence with 0 elements
89+
const EXPECTED_DEFAULT: &[u8] = &[0x30, 0x00];
90+
const EXPECTED_NOT_DEFAULT: &[u8] = &[0x30, 0x05, 0x61, 0x03, 0x01, 0x01, 0x00];
91+
// NOTE: The explicit tag number is just different
92+
const EXPECTED_MULTI_DEFAULT: &[u8] = &[0x30, 0x05, 0x62, 0x03, 0x01, 0x01, 0x00];
93+
// This version of the output is what would be generated without a default check.
94+
// Using this for backward compat. verification
95+
const EXPECTED_MULTI_DEFAULT_FIELD_ENCODED: &[u8] = &[
96+
0x30, 0x0a, 0x61, 0x03, 0x01, 0x01, 0xff, 0x62, 0x03, 0x01, 0x01, 0x00,
97+
];
98+
7099
let delegate_seq = DelegateSequence(Sequence { b: true });
71100
let inline_seq = InlineSequence { b: true };
72101
let field_seq = SequenceField { b: true };
@@ -84,6 +113,26 @@ fn works() {
84113
let inline_choice_enc = rasn::der::encode(&inline_choice).unwrap();
85114
let wrapped_choice_enc = rasn::der::encode(&wrapped_choice).unwrap();
86115

116+
// Set the field to match the default value to have it dropped
117+
let sequence_default = SequenceWithDefault { b: true };
118+
let sequence_non_default = SequenceWithDefault { b: false };
119+
let sequence_default_enc = rasn::der::encode(&sequence_default).unwrap();
120+
let sequence_non_default_enc = rasn::der::encode(&sequence_non_default).unwrap();
121+
// Verify it correctly includes encoded fields
122+
let sequence_multi_default = SequenceWithMultiDefault { b: true, b2: false };
123+
let sequence_multi_default_enc = rasn::der::encode(&sequence_multi_default).unwrap();
124+
125+
assert_eq!(sequence_non_default_enc, EXPECTED_NOT_DEFAULT);
126+
assert_eq!(sequence_default_enc, EXPECTED_DEFAULT);
127+
assert_eq!(sequence_multi_default_enc, EXPECTED_MULTI_DEFAULT);
128+
assert_eq!(
129+
sequence_multi_default,
130+
rasn::der::decode(&sequence_multi_default_enc).unwrap()
131+
);
132+
assert_eq!(
133+
sequence_multi_default,
134+
rasn::der::decode(EXPECTED_MULTI_DEFAULT_FIELD_ENCODED).unwrap()
135+
);
87136
assert_eq!(delegate_seq_enc, EXPECTED);
88137
assert_eq!(inline_seq_enc, EXPECTED);
89138
assert_eq!(field_seq_enc, EXPECTED);

0 commit comments

Comments
 (0)