#![allow(clippy::disallowed_names)]
use rasn::{types::*, *};
#[test]
fn enumerated() {
#[derive(AsnType, Clone, Copy, Debug, Encode, Decode, PartialEq)]
#[rasn(enumerated)]
enum Foo {
Ein,
Zwei,
Drei,
}
let ein = Foo::Ein;
let zwei = Foo::Zwei;
let drei = Foo::Drei;
assert_eq!(ein, ber::decode(&ber::encode(&ein).unwrap()).unwrap());
assert_eq!(zwei, ber::decode(&ber::encode(&zwei).unwrap()).unwrap());
assert_eq!(drei, ber::decode(&ber::encode(&drei).unwrap()).unwrap());
}
#[test]
fn choice() {
#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
#[rasn(choice)]
enum Choice {
Bar(bool),
#[rasn(tag(1))]
Baz(OctetString),
#[rasn(tag(2))]
Foo(OctetString),
}
let bar = Choice::Bar(true);
let baz = Choice::Baz(OctetString::from(vec![1, 2, 3, 4, 5]));
let foo = Choice::Foo(OctetString::from(vec![1, 2, 3, 4, 5]));
assert_eq!(foo, ber::decode(&ber::encode(&foo).unwrap()).unwrap());
assert_eq!(bar, ber::decode(&ber::encode(&bar).unwrap()).unwrap());
assert_eq!(baz, ber::decode(&ber::encode(&baz).unwrap()).unwrap());
#[derive(AsnType, Clone, Debug, Encode, Decode, PartialEq)]
struct ChoiceField {
choice: VecChoice,
}
#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq)]
#[rasn(choice)]
enum VecChoice {
#[rasn(tag(1))]
Bar(Vec<bool>),
#[rasn(tag(2))]
Foo(Vec<OctetString>),
}
let bar = ChoiceField {
choice: VecChoice::Bar(vec![true]),
};
let foo = ChoiceField {
choice: VecChoice::Foo(vec![OctetString::from(vec![1, 2, 3, 4, 5])]),
};
assert_eq!(foo, ber::decode(&ber::encode(&foo).unwrap()).unwrap());
assert_eq!(bar, ber::decode(&ber::encode(&bar).unwrap()).unwrap());
}
#[test]
fn sequence() {
#[derive(AsnType, Debug, Default, Decode, Encode, PartialEq)]
struct Bools {
a: bool,
#[rasn(tag(0))]
b: bool,
}
let raw = &[
0x30, 0x6, 1, 1, 0xff, 0x80, 1, 0, ][..];
let default = Bools { a: true, b: false };
assert_eq!(default, ber::decode(raw).unwrap());
assert_eq!(raw, &*ber::encode(&default).unwrap());
}
#[allow(dead_code)]
#[derive(AsnType, Debug, Decode, Encode, PartialEq)]
#[rasn(choice)]
enum NestedAnonChoiceStruct {
Foo {
x: bool,
#[rasn(tag(0))]
y: bool,
},
#[rasn(tag(0))]
Bar { x: bool, y: Integer },
}
#[test]
fn automatic_tags() {
#[derive(AsnType, Debug, Decode, Default, Encode, PartialEq)]
#[rasn(automatic_tags)]
struct Bools {
#[rasn(default)]
a: bool,
#[rasn(default)]
b: bool,
}
let raw = &[
0x30, 0x6, 0x80, 1, 0xFF, 0x81, 1, 0, ][..];
let default = Bools { a: true, b: false };
assert_eq!(default, ber::decode(raw).unwrap());
}
#[test]
fn list_in_single_attr() {
#[derive(AsnType, Debug, Default, Decode, Encode, PartialEq)]
#[rasn(delegate, tag(context, 0))]
struct Foo(u8);
#[derive(AsnType, Debug, Default, Decode, Encode, PartialEq)]
#[rasn(delegate)]
pub struct Bar(pub u8);
assert_eq!(Foo::TAG, Tag::new(Class::Context, 0));
assert_eq!(Bar::TAG, Integer::TAG);
}
#[derive(AsnType, Decode, Encode)]
#[rasn(choice)]
pub enum ExplicitChoice {
#[rasn(tag(explicit(1)))]
ByName,
#[rasn(tag(explicit(2)))]
ByKey,
}
#[derive(AsnType, Decode, Encode)]
#[rasn(choice)]
pub enum GenericEnum<T: Clone, const N: usize> {
FixedString(FixedOctetString<N>),
Sequence(Vec<T>),
}
#[derive(AsnType, Clone, Debug, Decode, Encode, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct BasicConstraints {
#[rasn(default)]
pub ca: bool,
pub path_len_constraint: Option<Integer>,
}
#[test]
fn delegated_newtype_wrapping() {
#[derive(AsnType, Debug, Decode, Encode, PartialEq)]
#[rasn(choice)]
enum Hash {
#[rasn(tag(explicit(0)))]
Sha256(String),
}
#[derive(AsnType, Debug, Decode, Encode, PartialEq)]
#[rasn(delegate)]
struct TransactionID(Hash);
#[derive(AsnType, Debug, Decode, Encode, PartialEq)]
#[rasn(delegate)]
struct PolicyID(TransactionID);
let policy_id1 = PolicyID(TransactionID(Hash::Sha256("abcdef".into())));
let ser = rasn::der::encode(&policy_id1).unwrap();
assert_eq!(&ser[..], &[160, 8, 12, 6, 97, 98, 99, 100, 101, 102]);
let policy_id2: PolicyID = rasn::der::decode(&ser[..]).unwrap();
assert_eq!(policy_id1, policy_id2);
}
#[test]
fn result_scoping() {
enum Error {}
type Result<T> = core::result::Result<T, Error>;
#[allow(dead_code)]
#[derive(rasn::AsnType, rasn::Encode, rasn::Decode)]
#[rasn(choice)]
enum Choose {
Single(String),
}
let _: Result<()> = Ok(());
}
#[test]
fn enum_with_encoder_tag_name_variants() {
#[allow(dead_code)]
#[derive(AsnType, Encode, Decode)]
#[rasn(choice)]
enum MyEnum {
#[rasn(tag(explicit(0)))]
HasConflictingFields {
#[rasn(tag(explicit(0)))]
encoder: String,
#[rasn(tag(explicit(1)))]
tag: String,
},
}
}
#[test]
fn explicit_identifiers() {
#[derive(AsnType, Encode, Decode)]
#[rasn(choice, identifier = "my-choice")]
enum MyChoice {
#[rasn(identifier = "has-alt-ident")]
HasAltIdent(()),
}
#[derive(AsnType, Encode, Decode, Debug, PartialEq, Clone, Copy)]
#[rasn(enumerated, identifier = "my-enum")]
enum MyEnum {
#[rasn(identifier = "has-alt-ident")]
HasAltIdent,
}
#[derive(AsnType, Encode, Decode)]
#[rasn(identifier = "my-struct")]
struct MyStruct {
#[rasn(identifier = "has-alt-ident")]
has_alt_ident: (),
}
#[derive(AsnType, Encode, Decode)]
#[rasn(identifier = "my-delegate")]
struct MyDelegate(());
assert_eq!(MyEnum::IDENTIFIER, Identifier(Some("my-enum")));
assert_eq!(MyEnum::IDENTIFIERS, ["has-alt-ident"]);
assert_eq!(MyChoice::IDENTIFIER, Identifier(Some("my-choice")));
assert_eq!(MyChoice::IDENTIFIERS, ["has-alt-ident"]);
assert_eq!(MyStruct::IDENTIFIER, Identifier(Some("my-struct")));
assert_eq!(
MyStruct::FIELDS.identifiers().collect::<Vec<_>>(),
vec!["has-alt-ident"]
);
assert_eq!(MyDelegate::IDENTIFIER, Identifier(Some("my-delegate")));
}
#[test]
fn test_constraint_values() {
#[derive(AsnType, Encode, Decode)]
struct MyConstrainedStruct {
#[rasn(size("10_000"))]
value: OctetString,
}
let my_struct = MyConstrainedStruct {
value: vec![1].into(),
};
let encoded = rasn::coer::encode(&my_struct);
assert!(encoded.is_err());
#[derive(AsnType, Encode, Decode)]
struct MyAnotherStruct {
#[rasn(value("1..=10_000"))]
value: u32,
}
let my_struct = MyAnotherStruct { value: 10_001 };
let encoded = rasn::uper::encode(&my_struct);
assert!(encoded.is_err());
let my_struct = MyAnotherStruct { value: 9999 };
let encoded = rasn::uper::encode(&my_struct);
assert!(encoded.is_ok());
}
#[test]
fn test_full_encode_decode_paths() {
use rasn::{Decode, Encode};
trait CustomCodec {
fn encode(&self) -> Result<Vec<u8>, ()>;
fn decode(bytes: &[u8]) -> Result<Self, ()>
where
Self: Sized;
}
impl CustomCodec for u32 {
fn encode(&self) -> Result<Vec<u8>, ()> {
Ok(self.to_be_bytes().to_vec())
}
fn decode(bytes: &[u8]) -> Result<Self, ()> {
if bytes.len() != 4 {
return Err(());
}
let mut arr = [0u8; 4];
arr.copy_from_slice(&bytes[..4]);
Ok(Self::from_be_bytes(arr))
}
}
#[derive(AsnType, Encode, Decode)]
struct Test {
key: u32,
value: rasn::types::OctetString,
}
let inst = Test {
key: 0,
value: "A test".as_bytes().into(),
};
let enc1 = <u32 as CustomCodec>::encode(&inst.key).unwrap();
let _dec1 = <u32 as CustomCodec>::decode(&enc1).unwrap();
}
#[test]
fn decode_enum_with_generics() {
#[derive(AsnType, Encode, Decode)]
#[rasn(choice)]
#[allow(dead_code)]
enum MyContainer<M> {
Struct {
#[rasn(tag(0))]
inner: Vec<M>,
},
StructNoGeneric {
#[rasn(tag(0))]
name: String,
},
Newtype(Vec<M>),
NewtypeNoGeneric(String),
}
#[derive(AsnType, Encode, Decode)]
#[rasn(choice)]
#[allow(dead_code)]
enum MyContainerExplicit<M> {
Struct {
#[rasn(tag(explicit(0)))]
inner: Vec<M>,
},
StructNoGeneric {
#[rasn(tag(explicit(0)))]
name: String,
},
Newtype(Vec<M>),
NewtypeNoGeneric(String),
}
}