Skip to content

Commit

Permalink
Merge pull request #16 from librasn/fix/nested-choice
Browse files Browse the repository at this point in the history
Fix/nested choice
  • Loading branch information
6d7a authored Apr 22, 2024
2 parents 2b4f6b3 + 4753284 commit 41e3990
Show file tree
Hide file tree
Showing 16 changed files with 654 additions and 250 deletions.
28 changes: 28 additions & 0 deletions rasn-compiler-tests/tests/edge_cases.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,34 @@
#![allow(non_camel_case_types)]
use rasn_compiler_tests::e2e_pdu;

#[test]
fn t() {
println!(
"{:?}",
rasn_compiler::Compiler::new()
.add_asn_literal(
r#"TestModule DEFINITIONS AUTOMATIC TAGS::= BEGIN
Restricted ::= Distinguished (second|fourth..sixth|eighth)
Distinguished ::= INTEGER {
first(1),
second(2),
third(3),
fourth(4),
fifth(5),
sixth(6),
seventh(7),
eighth(8),
ninth(9),
tenth(10),
} (1..10)
END"#
)
.compile_to_string()
.unwrap()
);
}

e2e_pdu!(
distinguished_value_range,
r#" Restricted ::= Distinguished (second|fourth..sixth|eighth)
Expand Down
2 changes: 1 addition & 1 deletion rasn-compiler-tests/tests/parse_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ fn compile_etsi() {
// .add_asn_by_path("../rasn-compiler/test_asn1/ngap_container.asn")
// .add_asn_by_path("../rasn-compiler/test_asn1/ngap_ies.asn")
// .add_asn_by_path("../rasn-compiler/test_asn1/ngap_pdus.asn")
.add_asn_by_path("../rasn-compiler/test_asn1/ngap_subset.asn")
.add_asn_by_path("../rasn-compiler/test_asn1/s1ap.asn")
.set_output_path("./tests")
.compile()
);
Expand Down
38 changes: 38 additions & 0 deletions rasn-compiler-tests/tests/structured_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,41 @@ e2e_pdu!(
alloc::vec![]
} "#
);

e2e_pdu!(
nested_choice_value,
r#"
NestedType ::= SEQUENCE {
choiceField CHOICE {
one INTEGER,
two BOOLEAN
}
}
nestedTypeVal NestedType ::= { choiceField one:4 }
"#,
r#"
#[doc = "Inner type"]
#[derive(AsnType,Debug,Clone,Decode,Encode,PartialEq)]
#[rasn(choice, automatic_tags)]
pub enum NestedTypeChoiceField {
one(Integer),
two(bool),
}
#[derive(AsnType,Debug,Clone,Decode,Encode,PartialEq)]
#[rasn(automatic_tags)]
pub struct NestedType{
#[rasn(identifier="choiceField")]
pub choice_field: NestedTypeChoiceField,
}
impl NestedType {
pub fn new(choice_field: NestedTypeChoiceField) -> Self {
Self { choice_field }
}
}
lazy_static! {
pub static ref NESTED_TYPE_VAL: NestedType = NestedType::new(NestedTypeChoiceField::one(Integer::from(4)));
} "#
);
18 changes: 18 additions & 0 deletions rasn-compiler/src/common.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/// The compiler generates code only in the `generator` module.
/// Therefore, all transformation of ASN.1 identifiers are specific
/// to a particular `Backend` implementation that the compiler uses.
/// For example, the `Rasn` backend unnests inner types and names
/// them with a specific prefix.
/// `INTERNAL_NESTED_TYPE_NAME_PREFIX` is a prefix that is prepended
/// to stringified type names of nested types (with the exception of
/// item types of array-like types) internally, so that they can be properly
/// identified by the individual compiler backends.
pub const INTERNAL_NESTED_TYPE_NAME_PREFIX: &str = "INNER$";
/// `INTERNAL_ITEM_TYPE_NAME_PREFIX` is a prefix that is prepended
/// to stringified type names of array-like types' item types, so that they
/// can be properly identified by the individual compiler backends.
pub const INTERNAL_ITEM_TYPE_NAME_PREFIX: &str = "ITEM$";
/// `INTERNAL_IO_FIELD_REF_TYPE_NAME_PREFIX` is a prefix that is prepended
/// to stringified type names of information object field reference types, so that they
/// can be properly identified by the individual compiler backends.
pub const INTERNAL_IO_FIELD_REF_TYPE_NAME_PREFIX: &str = "IOFR$";
26 changes: 14 additions & 12 deletions rasn-compiler/src/generator/rasn/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,6 @@ use crate::{
ASN1Information, ClassLink, InformationObjectClass, InformationObjectFields,
ObjectSetValue, ToplevelInformationDefinition,
},
utils::{
to_rust_const_case, to_rust_enum_identifier, to_rust_snake_case, to_rust_title_case,
},
ASN1Type, ASN1Value, ToplevelDefinition, ToplevelTypeDefinition, ToplevelValueDefinition,
BIT_STRING, BOOLEAN, GENERALIZED_TIME, INTEGER, NULL, OCTET_STRING, UTC_TIME,
},
Expand All @@ -41,8 +38,9 @@ impl Backend for Rust {
tlds: Vec<ToplevelDefinition>,
) -> Result<GeneratedModule, GeneratorError> {
if let Some((module_ref, _)) = tlds.first().and_then(|tld| tld.get_index().cloned()) {
let name = to_rust_snake_case(&module_ref.name);
let imports = module_ref.imports.iter().map(|import| {
let module = module_ref.borrow();
let name = to_rust_snake_case(&module.name);
let imports = module.imports.iter().map(|import| {
let module = to_rust_snake_case(&import.global_module_reference.module_reference);
let mut usages = Some(vec![]);
'imports: for usage in &import.types {
Expand Down Expand Up @@ -408,22 +406,26 @@ pub fn generate_value(tld: ToplevelValueDefinition) -> Result<TokenStream, Gener
quote!(OctetString),
value_to_tokens(&tld.value, None)?
),
ASN1Value::Choice(choice, inner) => {
if inner.is_const_type() {
ASN1Value::Choice {
variant_name,
inner_value,
..
} => {
if inner_value.is_const_type() {
call_template!(
const_choice_value_template,
tld,
to_rust_title_case(&tld.associated_type),
to_rust_enum_identifier(choice),
value_to_tokens(inner, None)?
to_rust_enum_identifier(variant_name),
value_to_tokens(inner_value, None)?
)
} else {
call_template!(
choice_value_template,
tld,
to_rust_title_case(&tld.associated_type),
to_rust_enum_identifier(choice),
value_to_tokens(inner, None)?
to_rust_enum_identifier(variant_name),
value_to_tokens(inner_value, None)?
)
}
}
Expand Down Expand Up @@ -451,7 +453,7 @@ pub fn generate_value(tld: ToplevelValueDefinition) -> Result<TokenStream, Gener
ASN1Value::LinkedStructLikeValue(s) => {
let members = s
.iter()
.map(|(_, val)| value_to_tokens(val.value(), None))
.map(|(_, ty, val)| value_to_tokens(val.value(), type_to_tokens(ty).ok().as_ref()))
.collect::<Result<Vec<TokenStream>, _>>()?;
call_template!(
sequence_or_set_value_template,
Expand Down
7 changes: 6 additions & 1 deletion rasn-compiler/src/generator/rasn/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,12 @@ fn generate(tld: ToplevelDefinition) -> Result<TokenStream, GeneratorError> {
| ASN1Type::External => generate_any(t),
ASN1Type::GeneralizedTime(_) => generate_generalized_time(t),
ASN1Type::UTCTime(_) => generate_utc_time(t),
ASN1Type::ChoiceSelectionType(_) => unreachable!(),
ASN1Type::ChoiceSelectionType(_) => Err(GeneratorError {
kind: GeneratorErrorType::Asn1TypeMismatch,
details: "Choice selection type should have been resolved at this point!"
.into(),
top_level_declaration: None,
}),
}
}
ToplevelDefinition::Value(v) => generate_value(v),
Expand Down
Loading

0 comments on commit 41e3990

Please sign in to comment.