Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix PER ObjectIdentifier, correct Alignment for Choice index encoding #202

Merged
merged 1 commit into from
Nov 14, 2023
Merged
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
16 changes: 16 additions & 0 deletions macros/src/enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,19 @@ impl Enum {
syn::Fields::Unit => quote!(#name::#ident => #identifier),
}
});
let tags = self.variants.iter().enumerate().map(|(i, v)| {
let ident = &v.ident;
let name = &self.name;
let variant_config = VariantConfig::new(v, generics, &self.config);
let variant_tag = variant_config.tag(i);
let tag_tokens = variant_tag.to_tokens(crate_root);

match &v.fields {
syn::Fields::Named(_) => quote!(#name::#ident { .. } => #tag_tokens),
syn::Fields::Unnamed(_) => quote!(#name::#ident (_) => #tag_tokens),
syn::Fields::Unit => quote!(#name::#ident => #tag_tokens),
}
});

let variants = self.variants.iter().enumerate().map(|(i, v)| {
let ident = &v.ident;
Expand Down Expand Up @@ -397,6 +410,9 @@ impl Enum {
let encode_variants = quote! {
encoder.encode_choice::<Self>(
Self::CONSTRAINTS,
match self {
#(#tags),*
},
match self {
#(#identifiers),*
},
Expand Down
33 changes: 33 additions & 0 deletions src/aper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ mod tests {
&[0x90, 0x27, 0x10, 0x80]
);
}

#[test]
fn visible_string() {
// B ::= VisibleString (SIZE (5))
Expand Down Expand Up @@ -433,6 +434,7 @@ mod tests {
&[0x01]
);
}

#[test]
fn issue_192() {
// https://github.com/XAMPPRocky/rasn/issues/192
Expand All @@ -459,4 +461,35 @@ mod tests {

round_trip!(aper, Message, msg, &[0, 1, 1]);
}

#[test]
fn issue_201() {
use crate as rasn;
use crate::prelude::*;

const T124_IDENTIFIER_KEY: &Oid = Oid::const_new(&[0, 0, 20, 124, 0, 1]);
#[derive(Debug, AsnType, Encode, rasn::Decode)]
#[rasn(choice, automatic_tags)]
enum Key {
#[rasn(tag(explicit(5)))]
Object(ObjectIdentifier),
H221NonStandard(OctetString),
}

#[derive(Debug, AsnType, rasn::Encode, rasn::Decode)]
#[rasn(automatic_tags)]
struct ConnectData {
t124_identifier_key: Key,
connect_pdu: OctetString,
}

let connect_pdu: OctetString = vec![0u8, 1u8, 2u8, 3u8].into();
let connect_data = ConnectData {
t124_identifier_key: Key::Object(T124_IDENTIFIER_KEY.into()),
connect_pdu,
};

let encoded = rasn::aper::encode(&connect_data).expect("failed to encode");
let _: ConnectData = rasn::aper::decode(&encoded).expect("failed to decode");
}
}
1 change: 1 addition & 0 deletions src/ber/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,6 +357,7 @@ impl crate::Encoder for Encoder {
fn encode_choice<E: Encode>(
&mut self,
_: Constraints,
_t: Tag,
_i: &str,
encode_fn: impl FnOnce(&mut Self) -> Result<Tag, Self::Error>,
) -> Result<Self::Ok, Self::Error> {
Expand Down
1 change: 1 addition & 0 deletions src/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,7 @@ pub trait Encoder {
fn encode_choice<E: Encode + crate::types::Choice>(
&mut self,
constraints: Constraints,
tag: Tag,
identifier: &'static str,
encode_fn: impl FnOnce(&mut Self) -> Result<Tag, Self::Error>,
) -> Result<Self::Ok, Self::Error>;
Expand Down
1 change: 1 addition & 0 deletions src/jer/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ impl crate::Encoder for Encoder {
fn encode_choice<E: crate::Encode + crate::types::Choice>(
&mut self,
_c: crate::types::Constraints,
_t: crate::types::Tag,
identifier: &'static str,
encode_fn: impl FnOnce(&mut Self) -> Result<crate::Tag, Self::Error>,
) -> Result<Self::Ok, Self::Error> {
Expand Down
3 changes: 2 additions & 1 deletion src/per/de.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,8 @@ impl<'input> crate::Decoder for Decoder<'input> {

fn decode_object_identifier(&mut self, _: Tag) -> Result<crate::types::ObjectIdentifier> {
let octets = self.decode_octets()?.into_vec();
crate::ber::decode(&octets)
let decoder = crate::ber::de::Decoder::new(&octets, crate::ber::de::DecoderOptions::ber());
decoder.decode_object_identifier_from_bytes(&octets)
}

fn decode_bit_string(&mut self, _: Tag, constraints: Constraints) -> Result<types::BitString> {
Expand Down
34 changes: 22 additions & 12 deletions src/per/enc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -835,7 +835,8 @@ impl crate::Encoder for Encoder {

fn encode_object_identifier(&mut self, tag: Tag, oid: &[u32]) -> Result<Self::Ok, Self::Error> {
self.set_bit(tag, true)?;
let der = crate::der::encode_scope(|encoder| encoder.encode_object_identifier(tag, oid))?;
let mut encoder = crate::der::enc::Encoder::new(crate::der::enc::EncoderOptions::der());
let der = encoder.object_identifier_as_bytes(oid)?;
self.encode_octet_string(tag, <_>::default(), &der)
}

Expand Down Expand Up @@ -1073,19 +1074,13 @@ impl crate::Encoder for Encoder {
fn encode_choice<E: Encode + crate::types::Choice>(
&mut self,
constraints: Constraints,
tag: Tag,
_: &str,
encode_fn: impl FnOnce(&mut Self) -> Result<Tag, Self::Error>,
) -> Result<Self::Ok, Self::Error> {
let mut buffer = BitString::new();
let mut choice_encoder = Self::new(self.options.without_set_encoding());
// Extensibility must be noted for byte alignment
if E::EXTENDED_VARIANTS.is_some() && self.options.aligned {
choice_encoder.parent_output_length = Some(1);
}

let tag = (encode_fn)(&mut choice_encoder)?;
let is_root_extension = crate::TagTree::tag_contains(&tag, E::VARIANTS);

self.encode_extensible_bit(&constraints, &mut buffer, || is_root_extension);
let variants = crate::types::variants::Variants::from_static(if is_root_extension {
E::VARIANTS
Expand All @@ -1102,15 +1097,30 @@ impl crate::Encoder for Encoder {
let bounds = if is_root_extension {
let variance = variants.len();
debug_assert!(variance > 0);

if variance != 1 {
Some(Some(variance))
} else {
if variance == 1 {
None
} else {
Some(Some(variance))
}
} else {
Some(None)
};

let mut choice_encoder = Self::new(self.options.without_set_encoding());
// Extensibility and index encoding size must be noted for byte alignment
let mut choice_bits_len = 0;
if E::EXTENDED_VARIANTS.is_some() && self.options.aligned {
choice_bits_len += 1;
}
choice_bits_len += if let Some(Some(variance)) = bounds {
crate::num::log2(variance as i128) as usize
} else {
0
};

choice_encoder.parent_output_length = Some(choice_bits_len);
let _tag = (encode_fn)(&mut choice_encoder)?;

match (index, bounds) {
(index, Some(Some(variance))) => {
// https://github.com/XAMPPRocky/rasn/issues/168
Expand Down
30 changes: 30 additions & 0 deletions src/uper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -977,4 +977,34 @@ mod tests {
&[96, 8, 5, 52]
);
}
#[test]
fn test_object_identifier() {
round_trip!(
uper,
ObjectIdentifier,
ObjectIdentifier::new(vec![1, 2]).unwrap(),
&[0x01u8, 0x2a]
);
round_trip!(
uper,
ObjectIdentifier,
ObjectIdentifier::new(vec![1, 2, 3321]).unwrap(),
&[0x03u8, 0x2a, 0x99, 0x79]
);
#[derive(AsnType, Debug, Decode, Encode, PartialEq)]
#[rasn(crate_root = "crate")]
struct B {
a: bool,
b: ObjectIdentifier,
}
round_trip!(
uper,
B,
B {
a: true,
b: ObjectIdentifier::new(vec![1, 2]).unwrap()
},
&[0x80, 0x95, 0x00]
);
}
}