pub mod de;
pub mod enc;
pub use self::{de::Decoder, enc::Encoder};
use crate::error::{DecodeError, EncodeError};
use crate::types::Constraints;
pub fn decode<T: crate::Decode>(input: &[u8]) -> Result<T, DecodeError> {
T::decode(&mut Decoder::<0, 0>::new(input, de::DecoderOptions::oer()))
}
pub fn decode_with_remainder<T: crate::Decode>(input: &[u8]) -> Result<(T, &[u8]), DecodeError> {
let decoder = &mut Decoder::<0, 0>::new(input, de::DecoderOptions::oer());
let decoded_instance = T::decode(decoder)?;
Ok((decoded_instance, decoder.remaining()))
}
pub fn encode<T: crate::Encode>(value: &T) -> Result<alloc::vec::Vec<u8>, EncodeError> {
let mut buffer = alloc::vec::Vec::with_capacity(core::mem::size_of::<T>());
let mut worker = alloc::vec::Vec::new();
let mut enc = Encoder::<0>::from_buffer(enc::EncoderOptions::coer(), &mut buffer, &mut worker);
value.encode(&mut enc)?;
Ok(enc.output())
}
pub fn encode_buf<T: crate::Encode>(
value: &T,
buffer: &mut alloc::vec::Vec<u8>,
) -> Result<(), EncodeError> {
let mut worker = alloc::vec::Vec::new();
let mut enc = Encoder::<0>::from_buffer(enc::EncoderOptions::coer(), buffer, &mut worker);
value.encode(&mut enc)?;
Ok(())
}
#[allow(dead_code)]
pub fn decode_with_constraints<T: crate::Decode>(
constraints: Constraints,
input: &[u8],
) -> Result<T, DecodeError> {
T::decode_with_constraints(
&mut Decoder::<0, 0>::new(input, de::DecoderOptions::oer()),
constraints,
)
}
#[allow(dead_code)]
pub fn encode_with_constraints<T: crate::Encode>(
constraints: Constraints,
value: &T,
) -> Result<alloc::vec::Vec<u8>, EncodeError> {
let mut buffer = alloc::vec::Vec::with_capacity(core::mem::size_of::<T>());
let mut worker = alloc::vec::Vec::new();
let mut enc = Encoder::<0>::from_buffer(enc::EncoderOptions::coer(), &mut buffer, &mut worker);
value.encode_with_constraints(&mut enc, constraints)?;
Ok(enc.output())
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum EncodingRules {
Oer,
Coer,
}
impl EncodingRules {
#[must_use]
pub fn is_coer(self) -> bool {
matches!(self, Self::Coer)
}
#[must_use]
pub fn is_oer(self) -> bool {
matches!(self, Self::Oer)
}
}
#[cfg(test)]
mod tests {
use crate as rasn;
use crate::prelude::*;
#[test]
fn test_bool() {
for value in 0x01..=0xFEu8 {
let bytes = [value];
decode_error!(coer, bool, &bytes);
decode_ok!(oer, bool, &bytes, true);
}
}
#[test]
fn test_length_determinant() {
decode_error!(coer, Integer, &[0x00, 0x00, 0x00, 0x01, 0x01]);
decode_error!(coer, Integer, &[0x00, 0x00, 0x00, 0x01, 0x01]);
decode_error!(coer, Integer, &[0b1000_0001, 0x01, 0x01]);
decode_ok!(oer, Integer, &[0b1000_0001, 0x01, 0x01], 1.into());
decode_error!(
coer,
OctetString,
&[0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x41, 0x41]
);
}
#[test]
#[cfg(feature = "f32")]
fn real_f32() {
round_trip!(oer, f32, 1.0, &[0x3f, 0x80, 0x00, 0x00]);
round_trip!(oer, f32, -1.0, &[0xbf, 0x80, 0x00, 0x00]);
}
#[test]
#[cfg(feature = "f64")]
fn real_f64() {
round_trip!(
oer,
f64,
1.0,
&[0x3f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
);
round_trip!(
oer,
f64,
-1.0,
&[0xbf, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
);
}
#[test]
fn test_sequence_of() {
#[derive(AsnType, Decode, Encode, Debug, Clone, PartialEq)]
struct TestA {
a: TestB,
}
#[derive(AsnType, Decode, Encode, Debug, Clone, PartialEq)]
struct TestB {
a: u8,
b: Option<u8>,
c: SequenceOf<u8>,
}
let data = [61, 11];
decode_error!(oer, TestA, &data);
let data: [u8; 108] = [30; 108];
decode_error!(oer, TestA, &data);
}
#[test]
fn test_enumerated() {
#[derive(AsnType, Decode, Encode, Debug, Clone, Copy, PartialEq)]
#[rasn(enumerated)]
enum Test {
A = 1,
B = 2,
}
#[derive(AsnType, Decode, Encode, Debug, Clone, Copy, PartialEq)]
#[rasn(enumerated)]
enum TestDefaults {
A,
B,
}
decode_error!(coer, Test, &[0x00, 0x00, 0x00, 0x01, 0x01]);
round_trip!(oer, Test, Test::A, &[0x01]);
round_trip!(oer, TestDefaults, TestDefaults::A, &[0x00]);
decode_ok!(oer, TestDefaults, &[0x00, 0x00], TestDefaults::A);
decode_error!(oer, Test, &[0x00, 0x01]);
decode_error!(oer, Test, &[0x00, 0x81, 0x01]);
decode_ok!(oer, Test, &[0x81, 0x01], Test::A);
decode_ok!(oer, Test, &[0x01], Test::A);
decode_error!(coer, Test, &[0b1000_0001, 0x01]);
decode_ok!(oer, Test, &[0b1000_0001, 0x01], Test::A);
}
#[test]
fn test_seq_preamble_unused_bits() {
use crate as rasn;
#[derive(AsnType, Decode, Encode, Clone, Debug, PartialEq, Eq)]
#[rasn(automatic_tags)]
pub struct SequenceOptionals {
pub it: Integer,
pub is: Option<OctetString>,
pub late: Option<Integer>,
}
let data = [0x10, 0x01, 0x2A];
decode_error!(coer, SequenceOptionals, &data);
let data = [0x0, 0x01, 0x2A];
round_trip!(
oer,
SequenceOptionals,
SequenceOptionals {
it: 42.into(),
is: None,
late: None
},
&data
);
}
#[test]
fn test_explicit_with_optional() {
#[derive(AsnType, Decode, Encode, Clone, Debug, PartialEq, Eq)]
pub struct SequenceOptionals {
#[rasn(tag(explicit(0)))]
pub it: Integer,
#[rasn(tag(explicit(1)))]
pub is: Option<OctetString>,
#[rasn(tag(explicit(2)))]
pub late: Option<Integer>,
}
let test_seq = SequenceOptionals {
it: 42.into(),
is: None,
late: None,
};
round_trip!(oer, SequenceOptionals, test_seq, &[0x00, 0x01, 0x2A]);
}
}