Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions macros/macros_impl/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,9 +653,16 @@ impl<'config> VariantConfig<'config> {
})
}
};
let (tag_tokens, is_tag_tree) = tag_tree;
let if_check = if is_tag_tree {
quote!(#crate_root::types::TagTree::tag_contains(&tag, &[#tag_tokens]))
} else {
quote!(#tag_tokens.eq(&tag))
};

Ok(quote! {
if #crate_root::types::TagTree::tag_contains(&tag, &[#tag_tree]) {

if #if_check {
#const_constraint
return #decode_op
}
Expand All @@ -677,11 +684,14 @@ impl<'config> VariantConfig<'config> {
})
}

pub fn tag_tree(&self) -> syn::Result<proc_macro2::TokenStream> {
/// Returns a tuple containing:
/// - The TokenStream representing the tag tree or a single tag
/// - A boolean indicating whether this is a complex tag tree (true) or a simple tag (false)
pub fn tag_tree(&self) -> syn::Result<(proc_macro2::TokenStream, bool)> {
let crate_root = &self.container_config.crate_root;
if self.tag.is_some() || self.container_config.automatic_tags {
let tag = self.tag()?.to_tokens(crate_root);
Ok(quote!(#crate_root::types::TagTree::Leaf(#tag)))
Ok((quote!(#tag), false))
} else {
let field_configs = self
.variant
Expand All @@ -697,9 +707,7 @@ impl<'config> VariantConfig<'config> {
.map(|f| f.tag_tree());

Ok(match self.variant.fields {
syn::Fields::Unit => {
quote!(#crate_root::types::TagTree::Leaf(<() as #crate_root::AsnType>::TAG))
}
syn::Fields::Unit => (quote!(<() as #crate_root::AsnType>::TAG), false),
syn::Fields::Named(_) => {
let error_message = format!(
"{}'s fields is not a valid \
Expand All @@ -708,20 +716,23 @@ impl<'config> VariantConfig<'config> {
self.variant.ident
);

quote!({
const FIELD_LIST: &'static [#crate_root::types::TagTree] = &[#(#field_tags),*];
const FIELD_TAG_TREE: #crate_root::types::TagTree = #crate_root::types::TagTree::Choice(FIELD_LIST);
const _: () = assert!(FIELD_TAG_TREE.is_unique(), #error_message);
#crate_root::types::TagTree::Leaf(#crate_root::types::Tag::SEQUENCE)
})
(
quote!({
const FIELD_LIST: &'static [#crate_root::types::TagTree] = &[#(#field_tags),*];
const FIELD_TAG_TREE: #crate_root::types::TagTree = #crate_root::types::TagTree::Choice(FIELD_LIST);
const _: () = assert!(FIELD_TAG_TREE.is_unique(), #error_message);
#crate_root::types::Tag::SEQUENCE
}),
false,
)
}
syn::Fields::Unnamed(_) => {
// Assert already checked in FieldConfig
assert_eq!(self.variant.fields.len(), 1);
let mut ty = self.variant.fields.iter().next().unwrap().ty.clone();
ty.strip_lifetimes();

quote!(<#ty as #crate_root::AsnType>::TAG_TREE)
(quote!(<#ty as #crate_root::AsnType>::TAG_TREE), true)
}
})
}
Expand Down
43 changes: 25 additions & 18 deletions macros/macros_impl/src/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,15 @@ impl Enum<'_> {
let field_tags = if self.config.choice {
variant_configs
.iter()
.map(super::config::VariantConfig::tag_tree)
.map(|config| {
config.tag_tree().map(|(tokens, is_tree)| {
if is_tree {
tokens
} else {
quote!(#crate_root::types::TagTree::Leaf(#tokens))
}
})
})
.collect::<Result<Vec<_>, _>>()?
} else {
Vec::new()
Expand Down Expand Up @@ -83,25 +91,27 @@ impl Enum<'_> {

let constraints_def = self.config.constraints.const_static_def(crate_root);

let (base_variants, extended_variants): (Vec<_>, Vec<_>) = variant_configs
.iter()
.zip(field_tags)
.partition_map(|(config, field_tag)| {
let extensible = self.config.constraints.extensible;

let (variant_tags, extended_variant_tags): (Vec<_>, Vec<_>) =
variant_configs.iter().partition_map(|config| {
if config.extension_addition {
either::Right(field_tag)
either::Right(config.tag().map(|tag| tag.to_tokens(crate_root)).unwrap())
} else {
either::Left(field_tag)
either::Left(config.tag().map(|tag| tag.to_tokens(crate_root)).unwrap())
}
});

let extensible = self.config.constraints.extensible;
let extended_const_variants = extensible
.then(|| quote!(Some(&[#(#extended_variants),*])))
let extended_variant_tags = extensible
.then(|| {
if extended_variant_tags.is_empty() {
quote!(Some(&[]))
} else {
quote!(Some(&[#(#extended_variant_tags),*]))
}
})
.unwrap_or(quote!(None));

// Check count of the root components in the choice
// https://github.com/XAMPPRocky/rasn/issues/168
// Choice index starts from zero, so we need to reduce variance by one
let variant_count = if self.variants.is_empty() {
0
} else {
Expand All @@ -121,11 +131,9 @@ impl Enum<'_> {

let choice_impl = self.config.choice.then(|| quote! {
impl #impl_generics #crate_root::types::Choice for #name #ty_generics #where_clause {
const VARIANTS: &'static [#crate_root::types::TagTree] = &[
#(#base_variants),*
];
const VARIANTS: &'static [#crate_root::types::Tag] = &[#(#variant_tags),*];
const VARIANCE_CONSTRAINT: #crate_root::types::Constraints = #variance_constraint;
const EXTENDED_VARIANTS: Option<&'static [#crate_root::types::TagTree]> = #extended_const_variants;
const EXTENDED_VARIANTS: Option<&'static [#crate_root::types::Tag]> = #extended_variant_tags;
const IDENTIFIERS: &'static [&'static str] = &[
#(#identifiers),*
];
Expand Down Expand Up @@ -426,7 +434,6 @@ impl Enum<'_> {
quote!(#name::#ident { #(#idents: #idents_prefixed),* } => { #encode_impl.map(|_| #tag_tokens) })
}
syn::Fields::Unnamed(_) => {
// Assert already checked in FieldConfig
assert_eq!(v.fields.len(), 1, "Tuple variants must contain only a single element.");
let constraints = variant_config
.constraints
Expand Down
10 changes: 7 additions & 3 deletions src/error/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use snafu::Snafu;
use snafu::{Backtrace, GenerateImplicitData};

use crate::de::Error;
use crate::types::{constraints::Bounded, variants::Variants, Tag};
use crate::types::{constraints::Bounded, Tag};
use crate::Codec;
use num_bigint::BigInt;

Expand Down Expand Up @@ -340,7 +340,11 @@ impl DecodeError {

/// Creates a wrapper around a missing choice index error from a given codec.
#[must_use]
pub fn choice_index_not_found(index: usize, variants: Variants, codec: Codec) -> Self {
pub fn choice_index_not_found(
index: usize,
variants: alloc::vec::Vec<Tag>,
codec: Codec,
) -> Self {
Self::from_kind(
DecodeErrorKind::ChoiceIndexNotFound { index, variants },
codec,
Expand Down Expand Up @@ -498,7 +502,7 @@ pub enum DecodeErrorKind {
/// The found index of the choice variant.
index: usize,
/// The variants checked for presence.
variants: Variants,
variants: alloc::vec::Vec<Tag>,
},

/// Choice index exceeds maximum possible address width.
Expand Down
17 changes: 8 additions & 9 deletions src/jer/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ use crate::{
de::Error,
error::{DecodeError, JerDecodeErrorKind},
types::{
variants, Any, BitString, BmpString, Constraints, Constructed, Date, DecodeChoice,
Enumerated, GeneralString, GeneralizedTime, GraphicString, Ia5String, NumericString,
ObjectIdentifier, Oid, PrintableString, SequenceOf, SetOf, Tag, TeletexString, UtcTime,
Utf8String, VisibleString,
Any, BitString, BmpString, Constraints, Constructed, Date, DecodeChoice, Enumerated,
GeneralString, GeneralizedTime, GraphicString, Ia5String, NumericString, ObjectIdentifier,
Oid, PrintableString, SequenceOf, SetOf, Tag, TeletexString, UtcTime, Utf8String,
VisibleString,
},
Decode,
};
Expand Down Expand Up @@ -660,14 +660,13 @@ impl Decoder {
.map(|(i, _)| (i, v))
})
.map_or(Tag::EOC, |(i, v)| {
match variants::Variants::from_slice(
&[D::VARIANTS, D::EXTENDED_VARIANTS.unwrap_or(&[])].concat(),
)
.get(i)
match &[D::VARIANTS, D::EXTENDED_VARIANTS.unwrap_or(&[])]
.concat()
.get(i)
{
Some(t) => {
self.stack.push(v.clone());
*t
**t
}
None => Tag::EOC,
}
Expand Down
6 changes: 2 additions & 4 deletions src/jer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ type ValueMap = Map<alloc::string::String, Value>;

use crate::{
error::{EncodeError, JerEncodeErrorKind},
types::{variants, Constraints, Identifier, IntegerType, Tag},
types::{Constraints, Identifier, IntegerType, Tag},
};

use crate::types::RealType;
Expand Down Expand Up @@ -487,9 +487,7 @@ impl crate::Encoder<'_> for Encoder {
encode_fn: impl FnOnce(&mut Self) -> Result<Tag, Self::Error>,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
let variants = variants::Variants::from_slice(
&[E::VARIANTS, E::EXTENDED_VARIANTS.unwrap_or(&[])].concat(),
);
let variants = &[E::VARIANTS, E::EXTENDED_VARIANTS.unwrap_or(&[])].concat();

let identifier = variants
.iter()
Expand Down
10 changes: 5 additions & 5 deletions src/oer/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -894,12 +894,12 @@ impl<'input, const RFC: usize, const EFC: usize> crate::Decoder for Decoder<'inp
{
let is_extensible = constraints.extensible();
let tag: Tag = self.parse_tag()?;
let is_root_extension = crate::types::TagTree::tag_contains(&tag, D::VARIANTS);
let is_extended_extension =
crate::types::TagTree::tag_contains(&tag, D::EXTENDED_VARIANTS.unwrap_or(&[]));
let is_root_extension = D::VARIANTS.contains(&tag);
if is_root_extension {
D::from_tag(self, tag)
} else if is_extensible && is_extended_extension {
return D::from_tag(self, tag);
}
let is_extended_extension = D::EXTENDED_VARIANTS.unwrap_or(&[]).contains(&tag);
if is_extensible && is_extended_extension {
let options = self.options;
let length = self.decode_length()?;
let bytes = self.extract_data_by_length(length)?;
Expand Down
24 changes: 12 additions & 12 deletions src/oer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,8 @@ impl<'buffer, const RCL: usize, const ECL: usize> Encoder<'buffer, RCL, ECL> {
// We must swap the first bit to show long form
// It is always zero by default with u8 type when value being < 128
length |= 0b_1000_0000;
self.output.extend_from_slice(&length.to_be_bytes());
self.output.reserve(1 + needed);
self.output.push(length);
self.output.extend_from_slice(&bytes.as_ref()[..needed]);
Ok(())
}
Expand All @@ -349,7 +350,7 @@ impl<'buffer, const RCL: usize, const ECL: usize> Encoder<'buffer, RCL, ECL> {
let (bytes, needed) = length.to_unsigned_bytes_be();
if length < 128 {
// First bit should be always zero when below 128: ITU-T X.696 8.6.4
buffer.extend_from_slice(&bytes.as_ref()[..needed]);
buffer.push(length as u8);
return Ok(());
}
let mut length_of_length = u8::try_from(needed).map_err(|err| {
Expand All @@ -367,7 +368,8 @@ impl<'buffer, const RCL: usize, const ECL: usize> Encoder<'buffer, RCL, ECL> {
// We must swap the first bit to show long form
// It is always zero by default with u8 type when value being < 128
length_of_length |= 0b_1000_0000;
buffer.extend_from_slice(&length_of_length.to_be_bytes());
buffer.reserve(1 + needed);
buffer.push(length_of_length);
buffer.extend_from_slice(&bytes.as_ref()[..needed]);
Ok(())
}
Expand Down Expand Up @@ -591,8 +593,7 @@ impl<'buffer, const RCL: usize, const ECL: usize> Encoder<'buffer, RCL, ECL> {
let mut cursor = self.cursor.extension_bitmap_cursor + self.worker.len();
self.output[self.cursor.extension_bitmap_cursor..cursor].copy_from_slice(self.worker);
self.worker.clear();
self.output[cursor..=cursor]
.copy_from_slice(&self.cursor.extension_missing_bits.to_be_bytes());
self.output[cursor] = self.cursor.extension_missing_bits;
cursor += 1;
for (i, bit) in self.extension_bitfield.1.iter().enumerate() {
extension_bitmap_buffer.set(i, *bit);
Expand Down Expand Up @@ -647,8 +648,7 @@ impl<'buffer, const RFC: usize, const EFC: usize> crate::Encoder<'buffer>
value: bool,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.output
.extend_from_slice(if value { &[0xffu8] } else { &[0x00u8] });
self.output.push(if value { 0xffu8 } else { 0x00u8 });
self.extend(tag);
Ok(())
}
Expand Down Expand Up @@ -698,7 +698,7 @@ impl<'buffer, const RFC: usize, const EFC: usize> crate::Encoder<'buffer>
// If the BitString is empty, length is one and initial octet is zero
if value.is_empty() {
Self::encode_length(self.output, 1)?;
self.output.extend_from_slice(&[0x00u8]);
self.output.push(0x00u8);
} else {
// TODO 22.7 X.680, NamedBitString and COER
// if self.options.encoding_rules.is_coer()
Expand Down Expand Up @@ -979,9 +979,9 @@ impl<'buffer, const RFC: usize, const EFC: usize> crate::Encoder<'buffer>
);
cursor.set_preamble_cursor(encoder.output.len());
// reserve bytes for preamble
for _ in 0..cursor.preamble_width {
encoder.output.push(0);
}
encoder
.output
.resize(encoder.output.len() + cursor.preamble_width, 0);

encoder.cursor = cursor;
encoder_scope(&mut encoder)?;
Expand Down Expand Up @@ -1100,7 +1100,7 @@ impl<'buffer, const RFC: usize, const EFC: usize> crate::Encoder<'buffer>
// Encode the value
let _tag = encode_fn(self)?;
debug_assert_eq!(_tag, tag);
let is_root_extension = crate::types::TagTree::tag_contains(&tag, E::VARIANTS);
let is_root_extension = E::VARIANTS.contains(&tag);
if is_root_extension {
// all good, correct data in the buffer already
} else {
Expand Down
6 changes: 3 additions & 3 deletions src/per/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1048,11 +1048,11 @@ impl<'input, const RFC: usize, const EFC: usize> crate::Decoder for Decoder<'inp
D: crate::types::DecodeChoice,
{
let is_extensible = self.parse_extensible_bit(&constraints)?;
let variants = crate::types::variants::Variants::from_static(if is_extensible {
let variants = if is_extensible {
D::EXTENDED_VARIANTS.unwrap_or(&[])
} else {
D::VARIANTS
});
};

let index = if variants.len() != 1 || is_extensible {
if is_extensible {
Expand Down Expand Up @@ -1080,7 +1080,7 @@ impl<'input, const RFC: usize, const EFC: usize> crate::Decoder for Decoder<'inp
};

let tag = variants.get(index).ok_or_else(|| {
DecodeError::choice_index_not_found(index, variants.clone(), self.codec())
DecodeError::choice_index_not_found(index, variants.to_vec(), self.codec())
})?;

if is_extensible {
Expand Down
10 changes: 5 additions & 5 deletions src/per/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1234,22 +1234,22 @@ impl<const RFC: usize, const EFC: usize> crate::Encoder<'_> for Encoder<RFC, EFC
) -> Result<Self::Ok, Self::Error> {
let mut buffer = BitString::new();

let is_root_extension = crate::types::TagTree::tag_contains(&tag, E::VARIANTS);
let is_root_extension = E::VARIANTS.contains(&tag);
self.encode_extensible_bit(&constraints, &mut buffer, || is_root_extension);
let variants = crate::types::variants::Variants::from_static(if is_root_extension {
let tags = if is_root_extension {
E::VARIANTS
} else {
E::EXTENDED_VARIANTS.unwrap_or(&[])
});
};

let index = variants
let index = tags
.iter()
.enumerate()
.find_map(|(i, &variant_tag)| (tag == variant_tag).then_some(i))
.ok_or_else(|| Error::variant_not_in_choice(self.codec()))?;

let bounds = if is_root_extension {
let variance = variants.len();
let variance = tags.len();
debug_assert!(variance > 0);
if variance == 1 {
None
Expand Down
Loading
Loading