Skip to content

Commit

Permalink
Merge pull request #84 from librasn/fix/414-inner-list-item
Browse files Browse the repository at this point in the history
fix(rasn): correctly bind nested list item constraints
  • Loading branch information
6d7a authored Mar 3, 2025
2 parents 604e8c8 + c1d5996 commit 4654087
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 16 deletions.
6 changes: 3 additions & 3 deletions rasn-compiler-tests/tests/parameterization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,13 @@ e2e_pdu! {
pub struct A2XPC5FlowBitRates {
#[rasn(identifier = "a2X-GuaranteedFlowBitRate")]
pub a2_x__guaranteed_flow_bit_rate: bool,
#[rasn(size("1.."), identifier = "iE-Extensions")]
pub i_e__extensions: Option<SequenceOf<A2XPC5FlowBitRatesIEExtensions>>,
#[rasn(identifier = "iE-Extensions")]
pub i_e__extensions: Option<A2XPC5FlowBitRatesIEExtensions>,
}
impl A2XPC5FlowBitRates {
pub fn new(
a2_x__guaranteed_flow_bit_rate: bool,
i_e__extensions: Option<SequenceOf<A2XPC5FlowBitRatesIEExtensions>>,
i_e__extensions: Option<A2XPC5FlowBitRatesIEExtensions>,
) -> Self {
Self {
a2_x__guaranteed_flow_bit_rate,
Expand Down
81 changes: 77 additions & 4 deletions rasn-compiler-tests/tests/structured_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,8 @@ e2e_pdu!(
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(choice, automatic_tags)]
pub enum TFCSReconfAddR12CtfcSize {
#[rasn(size("1..=1024"))]
ctfc8Bit(SequenceOf<TFCSReconfAddR12CtfcSizeCtfc8Bit>),
#[rasn(size("1..=1024"))]
ctfc16Bit(SequenceOf<TFCSReconfAddR12CtfcSizeCtfc16Bit>),
ctfc8Bit(TFCSReconfAddR12CtfcSizeCtfc8Bit),
ctfc16Bit(TFCSReconfAddR12CtfcSizeCtfc16Bit),
}
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(automatic_tags, identifier = "TFCS-ReconfAdd-r12")]
Expand Down Expand Up @@ -326,3 +324,78 @@ e2e_pdu!(
}
"#
);

e2e_pdu!(
anonymous_sequence_of_item_in_sequence_member,
r#"
Ticket ::= SEQUENCE {
ages SEQUENCE OF INTEGER (1..5),
passenger Passenger OPTIONAL
}
Passenger ::= ENUMERATED {
adult (0),
youth (1),
...
}
"#,
r#"
#[derive(AsnType, Debug, Clone, Copy, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(enumerated)]
#[non_exhaustive]
pub enum Passenger{
adult = 0,
youth = 1,
}
#[doc = " Anonymous SEQUENCE OF member "]
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(delegate, value("1..=5"), identifier = "INTEGER")]
pub struct AnonymousTicketAges(pub u8);
#[doc = " Inner type "]
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(delegate)]
pub struct TicketAges(pub SequenceOf<AnonymousTicketAges>);
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(automatic_tags)]
pub struct Ticket {
pub ages: TicketAges,
pub passenger: Option<Passenger>,
}
impl Ticket {
pub fn new(ages: TicketAges, passenger: Option<Passenger>) -> Self {
Self { ages, passenger }
}
}
"#
);

e2e_pdu!(
anonymous_set_of_item_in_choice_option,
r#"
Ticket ::= CHOICE {
age-set SET (SIZE (1..4)) OF INTEGER (1..5)
}
"#,
r#"
#[doc = " Anonymous SET OF member "]
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(delegate, value("1..=5"), identifier = "INTEGER")]
pub struct AnonymousTicketAgeSet(pub u8);
#[doc = " Inner type "]
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(delegate, size("1..=4"))]
pub struct TicketAgeSet(pub SetOf<AnonymousTicketAgeSet>);
#[derive(AsnType, Debug, Clone, Decode, Encode, PartialEq, Eq, Hash)]
#[rasn(choice, automatic_tags)]
pub enum Ticket {
#[rasn(identifier = "age-set")]
age_set(TicketAgeSet),
}
"#
);
31 changes: 23 additions & 8 deletions rasn-compiler/src/generator/rasn/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::str::FromStr;
use std::{ops::Not, str::FromStr};

use proc_macro2::{Ident, Literal, Punct, Spacing, Span, TokenStream};
use quote::{format_ident, quote, ToTokens, TokenStreamExt};
Expand Down Expand Up @@ -310,7 +310,7 @@ impl Rasn {
sequence_or_set.members.iter().enumerate().try_fold(
FormattedMembers::default(),
|mut acc, (i, m)| {
let nested = if self.needs_unnesting(&m.ty) {
let nested = if Self::needs_unnesting(&m.ty) {
Some(
self.generate_tld(ToplevelDefinition::Type(ToplevelTypeDefinition {
parameterization: None,
Expand Down Expand Up @@ -363,7 +363,13 @@ impl Rasn {
parent_name,
member.is_recursive,
)?;
all_constraints.append(&mut member.constraints.clone());
if Self::needs_unnesting(&member.ty) {
formatted_type_name = self.inner_name(&member.name, parent_name).to_token_stream();
// All constraints are applied on the delegate type
all_constraints = Vec::new();
} else {
all_constraints.append(&mut member.constraints.clone());
}
if (member.is_optional && member.default_value.is_none())
|| member.name.starts_with("ext_group_")
{
Expand Down Expand Up @@ -418,7 +424,7 @@ impl Rasn {
choice.options.iter().enumerate().try_fold(
FormattedOptions::default(),
|mut acc, (i, o)| {
let nested = if self.needs_unnesting(&o.ty) {
let nested = if Self::needs_unnesting(&o.ty) {
Some(
self.generate_tld(ToplevelDefinition::Type(ToplevelTypeDefinition {
parameterization: None,
Expand Down Expand Up @@ -463,13 +469,19 @@ impl Rasn {
parent_name: &String,
extension_annotation: TokenStream,
) -> Result<TokenStream, GeneratorError> {
let (mut all_constraints, formatted_type_name) = self.constraints_and_type_name(
let (mut all_constraints, mut formatted_type_name) = self.constraints_and_type_name(
&member.ty,
&member.name,
parent_name,
member.is_recursive,
)?;
all_constraints.append(&mut member.constraints.clone());
if Self::needs_unnesting(&member.ty) {
formatted_type_name = self.inner_name(&member.name, parent_name).to_token_stream();
// All constraints are applied on the delegate type
all_constraints = Vec::new();
} else {
all_constraints.append(&mut member.constraints.clone());
}
let range_annotations = self.format_range_annotations(
matches!(member.ty, ASN1Type::Integer(_)),
&all_constraints,
Expand Down Expand Up @@ -882,15 +894,18 @@ impl Rasn {
}
}

pub(crate) fn needs_unnesting(&self, ty: &ASN1Type) -> bool {
pub(crate) fn needs_unnesting(ty: &ASN1Type) -> bool {
match ty {
ASN1Type::Enumerated(_)
| ASN1Type::Choice(_)
| ASN1Type::Sequence(_)
| ASN1Type::Set(_) => true,
ASN1Type::SequenceOf(SequenceOrSetOf { element_type, .. })
| ASN1Type::SetOf(SequenceOrSetOf { element_type, .. }) => {
self.needs_unnesting(element_type)
Self::needs_unnesting(element_type)
|| element_type
.constraints()
.is_some_and(|c| c.is_empty().not())
}
_ => false,
}
Expand Down
Empty file.
44 changes: 44 additions & 0 deletions rasn-compiler/src/lexer/sequence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -823,4 +823,48 @@ integrityCheckValue ICV OPTIONAL
])
);
}

#[test]
fn parses_anonymous_sequence_of_item_in_field() {
assert_eq!(
sequence(
r#"
SEQUENCE {
ages SEQUENCE OF INTEGER (1..5)
}
"#
.into()
)
.unwrap()
.1,
ASN1Type::Sequence(SequenceOrSet {
components_of: vec![],
extensible: None,
constraints: vec![],
members: vec![SequenceOrSetMember {
name: "ages".into(),
tag: None,
ty: ASN1Type::SequenceOf(SequenceOrSetOf {
constraints: vec![],
element_type: Box::new(ASN1Type::Integer(Integer {
constraints: vec![Constraint::SubtypeConstraint(ElementSet {
set: ElementOrSetOperation::Element(SubtypeElement::ValueRange {
min: Some(ASN1Value::Integer(1,),),
max: Some(ASN1Value::Integer(5,),),
extensible: false,
},),
extensible: false,
},),],
distinguished_values: None,
},)),
is_recursive: false,
},),
default_value: None,
is_optional: false,
is_recursive: false,
constraints: vec![],
}],
},)
)
}
}
2 changes: 1 addition & 1 deletion rasn-compiler/src/validator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ impl Validator {

fn link(mut self) -> Result<(Self, Vec<CompilerError>), LinkerError> {
let mut warnings: Vec<CompilerError> = vec![];
// Linking of ASN1 values depends on linked ASN1 types, so we order the key colelction accordingly (note that we pop keys)
// Linking of ASN1 values depends on linked ASN1 types, so we order the key collection accordingly (note that we pop keys)
let mut keys = self
.tlds
.iter()
Expand Down

0 comments on commit 4654087

Please sign in to comment.