Skip to content

Commit

Permalink
Add common::Constraint which always provides a Tag for the current ty…
Browse files Browse the repository at this point in the history
…pe, fixes #13

Resolve all tags while augmenting the annotated structs with Constraint impls. It
is neccessary that to this state, the complex-type-references have already resolved
their tags. For this it it might be neccessary from now on to have all *.asn1 files
and their modules in scope while resolving the tags in the RustModel-to-Annotation
stage.

Quite a bit of work went into ensuring that no unncessary tags (meaning default tags)
are present in the annotated representation to prevent unnecessary bloat.

This will probably allow the SET and SET_OF branch to be merged soon #11 #10
  • Loading branch information
kellerkindt committed Oct 9, 2020
1 parent 6c3c93a commit cfb2101
Show file tree
Hide file tree
Showing 30 changed files with 553 additions and 289 deletions.
11 changes: 8 additions & 3 deletions asn1rs-model/src/ast/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,14 @@ fn parse_type_pre_stepped<'a>(
"complex" => {
let content;
parenthesized!(content in input);
let ident =
content.step(|c| c.ident().ok_or_else(|| c.error("Expected type identifier")))?;
Ok(Type::TypeReference(ident.to_string()))
let ident: syn::Ident = content.parse()?;
let _ = content.parse::<Token![,]>()?;
let tag_ident: syn::Ident = content.parse()?;
if !"tag".eq_ignore_ascii_case(&tag_ident.to_string()) {
return Err(input.error("Expected identifier 'tag'"));
}
let tag = AttrTag::parse(&content)?;
Ok(Type::TypeReference(ident.to_string(), Some(tag.0)))
}
"option" | "optional" => {
let content;
Expand Down
27 changes: 17 additions & 10 deletions asn1rs-model/src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ mod tag;

use crate::ast::attribute::{Context, DefinitionHeader, Transparent};
use crate::ast::constants::ConstLit;
use crate::model::{Asn as AsnModelType, EnumeratedVariant, Sequence, TagProperty};
use crate::model::{Asn as AsnModelType, EnumeratedVariant, Sequence, TagProperty, TagResolver};
use crate::model::{Choice, ChoiceVariant, Definition, Enumerated, Field, Model, Type};
use attribute::AsnAttribute;
use quote::quote;
Expand Down Expand Up @@ -70,6 +70,13 @@ pub fn expand(definition: Option<Definition<AsnModelType>>) -> Vec<TokenStream>
if let Some(definition) = definition {
model.definitions.push(definition);
use crate::gen::rust::walker::AsnDefWriter;

if cfg!(feature = "debug-proc-macro") {
println!("---------- parsed definition to rust begin ----------");
println!("{:?}", model.to_rust());
println!("---------- parsed definition to rust end ----------");
println!();
}
additional_impl
.push(TokenStream::from_str(&AsnDefWriter::stringify(&model.to_rust())).unwrap());
}
Expand Down Expand Up @@ -286,14 +293,14 @@ fn parse_choice(
let extensible_after =
find_extensible_index(&asn, asn_span, variants.iter().map(|v| v.name()))?;

let choice = Type::Choice(
Choice::from_variants(variants.into_iter()).with_extension_after(extensible_after),
);

let tag = asn.tag.or_else(|| TagResolver::resolve_default(&choice));

Ok((
Some(Definition(
enm.ident.to_string(),
Type::Choice(
Choice::from_variants(variants.into_iter()).with_extension_after(extensible_after),
)
.opt_tagged(asn.tag),
)),
Some(Definition(enm.ident.to_string(), choice.opt_tagged(tag))),
Item::Enum(enm),
))
}
Expand Down Expand Up @@ -356,8 +363,8 @@ fn into_asn<C: Context<Primary = Type>>(
) -> Option<AsnModelType> {
Some(AsnModelType {
tag: asn.tag,
r#type: if let Type::TypeReference(_) = asn.primary {
Type::TypeReference(quote! { #ty }.to_string())
r#type: if let Type::TypeReference(_, empty_tag) = asn.primary {
Type::TypeReference(quote! { #ty }.to_string(), empty_tag.or(asn.tag))
} else {
if let Type::Integer(int) = asn.primary.no_optional_mut() {
asn.consts
Expand Down
11 changes: 10 additions & 1 deletion asn1rs-model/src/gen/rust/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,16 @@ impl RustCodeGenerator {
Type::Sequence(_) => (Cow::Borrowed("sequence"), Vec::default()),
Type::Enumerated(_) => (Cow::Borrowed("enumerated"), Vec::default()),
Type::Choice(_) => (Cow::Borrowed("choice"), Vec::default()),
Type::TypeReference(inner) => (Cow::Borrowed("complex"), vec![inner.clone()]),
Type::TypeReference(inner, tag) => (
Cow::Borrowed("complex"),
vec![
Some(inner.clone()),
tag.clone().map(Self::asn_attribute_tag),
]
.into_iter()
.flatten()
.collect(),
),
};
if parameters.is_empty() {
name.into_owned()
Expand Down
21 changes: 11 additions & 10 deletions asn1rs-model/src/gen/rust/protobuf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ impl ProtobufSerializer {
));

match aliased.clone().into_inner_type() {
RustType::Complex(custom) => {
RustType::Complex(custom, _asn_tag) => {
if aliased.as_no_option().is_vec() {
block_reader.line(format!("me.0.push({}::read_protobuf(reader)?);", custom))
} else {
Expand Down Expand Up @@ -147,7 +147,7 @@ impl ProtobufSerializer {

for (prev_tag, field) in fields.iter().enumerate() {
match &field.r#type().clone().into_inner_type() {
RustType::Complex(name) => {
RustType::Complex(name, _asn_tag) => {
let mut block_case = Block::new(&format!(
"{} => read_{}{}(",
prev_tag + 1,
Expand Down Expand Up @@ -261,12 +261,13 @@ impl ProtobufSerializer {
format!(" if tag.1 == {}Format::LengthDelimited", Self::CODEC)
},
));
let complex_name =
if let RustType::Complex(name) = variant.r#type().clone().into_inner_type() {
Some(name)
} else {
None
};
let complex_name = if let RustType::Complex(name, _asn_tag) =
variant.r#type().clone().into_inner_type()
{
Some(name)
} else {
None
};
if let Some(complex_name) = complex_name {
block_case.line("let bytes = reader.read_bytes()?;");
block_case.line(format!(
Expand Down Expand Up @@ -339,7 +340,7 @@ impl ProtobufSerializer {
}
));
match aliased.clone().into_inner_type() {
RustType::Complex(_) => {
RustType::Complex(_, _asn_tag) => {
block_for.line(format!(
"writer.write_tag({}, {})?;",
tag,
Expand Down Expand Up @@ -409,7 +410,7 @@ impl ProtobufSerializer {
RustType::Vec(..) => {
Self::impl_write_for_vec_attribute(&mut block, field_type, &field_name, tag);
}
RustType::Complex(_) => {
RustType::Complex(_, _) => {
let format_line = format!(
"{}{}.{}_format()",
if deny_self || field_type.is_option() {
Expand Down
4 changes: 2 additions & 2 deletions asn1rs-model/src/gen/rust/psql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ impl PsqlInserter {
load_block.line(&format!(
"let rows = transaction.prepare_cached(\"{}\")?.query(&[&row.get_opt::<usize, i32>(0).ok_or_else(PsqlError::no_result)??])?;",

if let RustType::Complex(complex) = rust.clone().into_inner_type() {
if let RustType::Complex(complex, _tag) = rust.clone().into_inner_type() {
struct_list_entry_select_referenced_value_statement(
struct_name,
name,
Expand All @@ -509,7 +509,7 @@ impl PsqlInserter {
}
));
let mut rows_foreach = Block::new("for row in rows.iter()");
if let RustType::Complex(complex) = rust.clone().into_inner_type() {
if let RustType::Complex(complex, _tag) = rust.clone().into_inner_type() {
rows_foreach.line(&format!(
"vec.push({}::load_from(transaction, &row)?);",
complex
Expand Down
10 changes: 3 additions & 7 deletions asn1rs-model/src/gen/rust/uper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ impl UperSerializer {
block.push_block(if_block);
block.push_block(else_block);
}
RustType::Complex(_inner) => {
RustType::Complex(_inner, _tag) => {
block.line(format!("{}::read_uper(reader)?", type_name));
}
};
Expand Down Expand Up @@ -445,11 +445,7 @@ impl UperSerializer {
local_name,
if field_name
.as_ref()
.map_or(false, |f| if let Member::Local(..) = f {
true
} else {
false
})
.map_or(false, |f| matches!(f, Member::Local(..)))
{
""
} else {
Expand Down Expand Up @@ -486,7 +482,7 @@ impl UperSerializer {
);
block.push_block(if_block);
}
RustType::Complex(_inner) => {
RustType::Complex(_inner, _tag) => {
block.line(format!(
"{}.write_uper(writer)?;",
&field_name.map_or_else(
Expand Down
Loading

0 comments on commit cfb2101

Please sign in to comment.