use alloc::{
borrow::Cow,
string::{String, ToString},
vec::Vec,
};
use core::num::NonZeroUsize;
use nom::Needed;
use crate::{
Codec,
de::{Decode, Error as _},
oer::EncodingRules,
types::{
self, Any, BitString, BmpString, Constraints, Constructed, DecodeChoice, Enumerated,
GeneralString, GeneralizedTime, GraphicString, Ia5String, IntegerType, NumericString,
ObjectIdentifier, PrintableString, SetOf, Tag, TeletexString, UtcTime, VisibleString,
fields::{Field, Fields},
},
};
use bitvec::{order::Msb0, view::BitView};
use crate::error::{CoerDecodeErrorKind, DecodeError, DecodeErrorKind, OerDecodeErrorKind};
#[derive(Clone, Copy, Debug)]
pub struct DecoderOptions {
encoding_rules: EncodingRules, remaining_depth: usize,
}
impl DecoderOptions {
#[must_use]
pub const fn oer() -> Self {
Self {
encoding_rules: EncodingRules::Oer,
remaining_depth: 128,
}
}
#[must_use]
pub const fn coer() -> Self {
Self {
encoding_rules: EncodingRules::Coer,
remaining_depth: 128,
}
}
#[must_use]
fn current_codec(self) -> Codec {
match self.encoding_rules {
EncodingRules::Oer => Codec::Oer,
EncodingRules::Coer => Codec::Coer,
}
}
}
pub struct Decoder<'input, const RFC: usize = 0, const EFC: usize = 0> {
input: &'input [u8],
options: DecoderOptions,
fields: ([Option<Field>; RFC], usize),
extension_fields: Option<Fields<EFC>>,
extensions_present: Option<Option<([Option<Field>; EFC], usize)>>,
}
impl<'input, const RFC: usize, const EFC: usize> Decoder<'input, RFC, EFC> {
#[must_use]
pub fn new(input: &'input [u8], options: DecoderOptions) -> Self {
Self {
input,
options,
fields: ([None; RFC], 0),
extension_fields: <_>::default(),
extensions_present: <_>::default(),
}
}
#[must_use]
fn codec(&self) -> Codec {
self.options.current_codec()
}
#[must_use]
pub fn remaining(&self) -> &'input [u8] {
self.input
}
fn parse_one_byte(&mut self) -> Result<u8, DecodeError> {
let (first, rest) = self.input.split_first().ok_or_else(|| {
DecodeError::parser_fail(
"Unexpected end of data when parsing single byte from &[u8]".to_string(),
self.codec(),
)
})?;
self.input = rest;
Ok(*first)
}
fn parse_tag(&mut self) -> Result<Tag, DecodeError> {
use crate::types::Class;
let first_byte = self.parse_one_byte()?;
let class = match first_byte >> 6 {
0b00 => Class::Universal,
0b01 => Class::Application,
0b10 => Class::Context,
0b11 => Class::Private,
class => return Err(OerDecodeErrorKind::InvalidTagClassOnChoice { class }.into()),
};
let tag_number = first_byte & 0b0011_1111;
if tag_number == 0b11_1111 {
let mut tag_number = 0u32;
let mut next_byte = self.parse_one_byte()?;
if next_byte.trailing_zeros() >= 7 || next_byte == 0 {
return Err(OerDecodeErrorKind::invalid_tag_number_on_choice(u32::from(
next_byte & 0b1000_0000,
)));
}
loop {
tag_number = tag_number
.checked_shl(7)
.ok_or(OerDecodeErrorKind::invalid_tag_number_on_choice(tag_number))?
| u32::from(next_byte & 0b0111_1111);
if next_byte & 0b1000_0000 == 0 {
break;
}
next_byte = self.parse_one_byte()?;
}
Ok(Tag::new(class, tag_number))
} else {
Ok(Tag::new(class, u32::from(tag_number)))
}
}
fn decode_length(&mut self) -> Result<usize, DecodeError> {
let possible_length = self.parse_one_byte()?;
if possible_length < 128 {
Ok(usize::from(possible_length))
} else {
let length = possible_length & 0x7fu8;
if length == 0 {
return Err(DecodeError::from_kind(
DecodeErrorKind::ZeroLengthOfLength,
self.codec(),
));
}
let (data, rest) = self
.input
.split_at_checked(length as usize)
.ok_or_else(|| {
DecodeError::parser_fail(
alloc::format!("Unexpected end of data when parsing length by length of length {length} from &[u8]"
),
self.codec(),
)
})?;
self.input = rest;
if self.options.encoding_rules.is_coer() && data.first() == Some(&0) {
return Err(CoerDecodeErrorKind::NotValidCanonicalEncoding {
msg: "Length value should not have leading zeroes in COER".to_string(),
}
.into());
}
let length = usize::try_from_unsigned_bytes(data, self.codec())?;
if length < 128 && self.options.encoding_rules.is_coer() {
return Err(CoerDecodeErrorKind::NotValidCanonicalEncoding {
msg: "Length determinant could have been encoded in short form.".to_string(),
}
.into());
}
Ok(length)
}
}
fn extract_data_by_length(&mut self, length: usize) -> Result<&'input [u8], DecodeError> {
if length == 0 {
return Ok(&[]);
}
let (data, rest) = self.input.split_at_checked(length).ok_or_else(|| {
DecodeError::incomplete(
Needed::Size(NonZeroUsize::new(length - self.input.len()).unwrap()),
self.codec(),
)
})?;
self.input = rest;
Ok(data)
}
fn decode_integer_from_bytes<I: crate::types::IntegerType>(
&mut self,
signed: bool,
length: Option<usize>,
) -> Result<I, DecodeError> {
let final_length = match length {
Some(l) => l,
None => self.decode_length()?,
};
let codec = self.codec();
let coer = self.options.encoding_rules.is_coer();
let data = self.extract_data_by_length(final_length)?;
if coer && length.is_none() && data.len() >= 2 {
if !signed && data.first() == Some(&0) {
return Err(CoerDecodeErrorKind::NotValidCanonicalEncoding {
msg: "Leading zeros are not allowed on unsigned Integer value in COER."
.to_string(),
}
.into());
} else if signed && data[0] == (((data[1] & 0x80) as i8 >> 7) as u8) {
return Err(CoerDecodeErrorKind::NotValidCanonicalEncoding {
msg: "Leading sign bits are not allowed on signed Integer value in COER."
.to_string(),
}
.into());
}
}
if signed {
Ok(I::try_from_signed_bytes(data, codec)?)
} else {
Ok(I::try_from_unsigned_bytes(data, codec)?)
}
}
fn decode_integer_with_constraints<I: crate::types::IntegerType>(
&mut self,
constraints: &Constraints,
) -> Result<I, DecodeError> {
if let Some(value) = constraints.value() {
let (signed, octets) = if value.extensible.is_some() {
(true, None)
} else {
(value.constraint.get_sign(), value.constraint.get_range())
};
let integer = self.decode_integer_from_bytes::<I>(signed, octets.map(usize::from))?;
if let Some(constraint_integer) = integer.to_i128() {
if value.constraint.contains(&constraint_integer) {
Ok(integer)
} else {
Err(DecodeError::value_constraint_not_satisfied(
integer.to_bigint().unwrap_or_default(),
value.constraint.value,
self.codec(),
))
}
} else {
Err(DecodeError::value_constraint_not_satisfied(
integer.to_bigint().unwrap_or_default(),
value.constraint.value,
self.codec(),
))
}
} else {
self.decode_integer_from_bytes::<I>(true, None)
}
}
fn parse_bit_string(&mut self, constraints: &Constraints) -> Result<BitString, DecodeError> {
if let Some(size) = constraints.size() {
if size.constraint.is_fixed() && size.extensible.is_none() {
let length = size.constraint.as_start().ok_or_else(|| {
Err(DecodeError::size_constraint_not_satisfied(
None,
"Fixed size constraint should have value".to_string(),
self.codec(),
))
});
return match length {
Ok(length) => {
let bytes_required = (*length).div_ceil(8);
let data = &self
.extract_data_by_length(bytes_required)?
.view_bits::<Msb0>()[..*length];
Ok(data.into())
}
Err(e) => e,
};
}
}
let length = self.decode_length()?;
if length == 0 {
return Ok(BitString::new());
}
let num_unused_bits = self.parse_one_byte()?;
if length == 1 && num_unused_bits > 0 {
return Err(OerDecodeErrorKind::invalid_bit_string(
"Length includes only initial octet. There cannot be unused bits on the subsequent octects as there isn't any.".to_string(),
));
}
if num_unused_bits > 7 {
return Err(OerDecodeErrorKind::invalid_bit_string(
"Marked number of unused bits should be less than 8 when decoding OER".to_string(),
));
}
let data_bit_length: usize = (&length - 1usize).checked_mul(8).ok_or_else(|| {
DecodeError::length_exceeds_platform_width(
"Total length exceeds BitSlice max usize when decoding BitString".to_string(),
self.codec(),
)
})?;
let data = &self.extract_data_by_length(length - 1)?.view_bits::<Msb0>()
[..(data_bit_length - num_unused_bits as usize)];
Ok(data.into())
}
fn parse_known_multiplier_string<
T: crate::types::strings::StaticPermittedAlphabet
+ crate::types::AsnType
+ for<'a> TryFrom<&'a [u8], Error = crate::error::strings::PermittedAlphabetError>,
>(
&mut self,
constraints: &Constraints,
) -> Result<T, DecodeError> {
if let Some(size) = constraints.size() {
if size.constraint.is_fixed() && size.extensible.is_none() {
let data = self.extract_data_by_length(*size.constraint.as_start().unwrap())?;
return T::try_from(data)
.map_err(|e| DecodeError::permitted_alphabet_error(e, self.codec()));
}
}
let length = self.decode_length()?;
T::try_from(self.extract_data_by_length(length)?)
.map_err(|e| DecodeError::permitted_alphabet_error(e, self.codec()))
}
#[track_caller]
fn require_field(&mut self, tag: Tag) -> Result<bool, DecodeError> {
let (fields, index) = &mut self.fields;
let Some(field) = fields.get(*index) else {
return Err(DecodeError::missing_tag_class_or_value_in_sequence_or_set(
tag.class,
tag.value,
self.codec(),
));
};
*index += 1;
match field {
Some(field) if field.tag_tree.smallest_tag() == tag => Ok(true),
None => Ok(false),
_ => Err(DecodeError::missing_tag_class_or_value_in_sequence_or_set(
tag.class,
tag.value,
self.codec(),
)),
}
}
fn extension_is_present(&mut self) -> Result<Option<&Field>, DecodeError> {
let codec = self.codec();
let Some(Some((fields, index))) = self.extensions_present.as_mut() else {
return Err(DecodeError::type_not_extensible(codec));
};
let field = fields
.get(*index)
.ok_or_else(|| DecodeError::type_not_extensible(codec))?;
*index += 1;
Ok(field.as_ref())
}
fn parse_extension_header(&mut self) -> Result<bool, DecodeError> {
match self.extensions_present {
Some(Some(_)) => return Ok(true),
Some(None) => (),
None => return Ok(false),
}
let extensions_length = self.decode_length()?;
if extensions_length < 1u8.into() {
return Err(OerDecodeErrorKind::invalid_extension_header(
"Extension length should be at least 1 byte".to_string(),
));
}
let extension_fields = self
.extension_fields
.ok_or_else(|| DecodeError::type_not_extensible(self.codec()))?;
let bitfield_bytes = self.extract_data_by_length(extensions_length)?;
let (first_byte, bitfield) = bitfield_bytes.split_first().ok_or_else(|| {
OerDecodeErrorKind::invalid_extension_header("Missing initial octet".to_string())
})?;
let unused_bits = *first_byte as usize;
if unused_bits > 7 || unused_bits > bitfield.len() * 8 {
return Err(OerDecodeErrorKind::invalid_extension_header(
"Invalid extension bitfield initial octet".to_string(),
));
}
let mut fields: [Option<Field>; EFC] = [None; EFC];
for (i, field) in extension_fields.iter().enumerate() {
let byte_idx = i / 8;
let bit_idx = 7 - (i & 7); let is_set = byte_idx < bitfield.len() && (bitfield[byte_idx] & (1 << bit_idx)) != 0;
if field.is_not_optional_or_default() && !is_set {
return Err(DecodeError::required_extension_not_present(
field.tag,
self.codec(),
));
} else if is_set {
fields[i] = Some(field);
}
}
self.extensions_present = Some(Some((fields, 0)));
Ok(true)
}
fn parse_preamble<const RC: usize, const EC: usize, D>(
&mut self,
) -> Result<([bool; RC], bool), DecodeError>
where
D: Constructed<RC, EC>,
{
let is_extensible = D::IS_EXTENSIBLE;
let preamble_width =
D::FIELDS.number_of_optional_and_default_fields() + usize::from(is_extensible);
let bytes = self.extract_data_by_length(preamble_width.div_ceil(8))?;
let mut result = [false; RC];
let mut extensible_present = false;
for i in 0..preamble_width {
let byte_idx = i / 8;
let bit_idx = 7 - (i & 7);
let is_set: bool = (bytes[byte_idx] & (1 << bit_idx)) != 0;
if i == 0 && is_extensible {
extensible_present = is_set;
} else if i - usize::from(is_extensible) < RC {
result[i - usize::from(is_extensible)] = is_set;
}
}
let remaining_bits_start = preamble_width;
for i in remaining_bits_start..bytes.len() * 8 {
let byte_idx = i / 8;
let bit_idx = 7 - (i & 7);
if (bytes[byte_idx] & (1 << bit_idx)) != 0 {
return Err(OerDecodeErrorKind::invalid_preamble(
"Preamble unused bits should be all zero.".to_string(),
));
}
}
Ok((result, extensible_present))
}
fn check_recursion_depth(&self) -> Result<(), DecodeError> {
if self.options.remaining_depth == 0 {
return Err(DecodeError::from_kind(
DecodeErrorKind::ExceedsMaxParseDepth,
self.codec(),
));
}
Ok(())
}
}
impl<'input, const RFC: usize, const EFC: usize> crate::Decoder for Decoder<'input, RFC, EFC> {
type Ok = ();
type Error = DecodeError;
type AnyDecoder<const R: usize, const E: usize> = Decoder<'input, R, E>;
fn codec(&self) -> Codec {
self.codec()
}
fn decode_any(&mut self, tag: Tag) -> Result<Any, Self::Error> {
Ok(Any::new(
self.decode_octet_string(tag, Constraints::default())?,
))
}
fn decode_bit_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<BitString, Self::Error> {
self.parse_bit_string(&constraints)
}
fn decode_bool(&mut self, _: Tag) -> Result<bool, Self::Error> {
let byte = self.parse_one_byte()?;
Ok(match byte {
0 => false,
0xFF => true,
_ if self.options.encoding_rules.is_oer() => true,
_ => {
return Err(DecodeError::from_kind(
DecodeErrorKind::InvalidBool { value: byte },
self.codec(),
));
}
})
}
fn decode_enumerated<E: Enumerated>(&mut self, _: Tag) -> Result<E, Self::Error> {
let byte = self.parse_one_byte()?;
if byte < 128 {
E::from_discriminant(isize::from(byte))
.ok_or_else(|| DecodeError::discriminant_value_not_found(byte.into(), self.codec()))
} else {
let length = byte & 0x7fu8;
let discriminant: isize = self
.decode_integer_from_bytes(true, Some(length.into()))
.map_err(|e| {
if matches!(&*e.kind, DecodeErrorKind::IntegerOverflow { .. }) {
DecodeError::length_exceeds_platform_width(
"Enumerated discriminant value too large for this platform."
.to_string(),
self.codec(),
)
} else {
e
}
})?;
if (0..128).contains(&discriminant) && self.options.encoding_rules.is_coer() {
return Err(CoerDecodeErrorKind::NotValidCanonicalEncoding {
msg: "Enumerated discriminant should have been encoded in short form."
.to_string(),
}
.into());
}
E::from_discriminant(discriminant).ok_or_else(|| {
DecodeError::discriminant_value_not_found(discriminant, self.codec())
})
}
}
fn decode_integer<I: crate::types::IntegerType>(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<I, Self::Error> {
self.decode_integer_with_constraints::<I>(&constraints)
}
fn decode_real<R: crate::types::RealType>(
&mut self,
_: Tag,
_: Constraints,
) -> Result<R, Self::Error> {
let octets = self.extract_data_by_length(R::BYTE_WIDTH)?;
R::try_from_ieee754_bytes(octets)
.map_err(|_| DecodeError::from_kind(DecodeErrorKind::InvalidRealEncoding, self.codec()))
}
fn decode_null(&mut self, _: Tag) -> Result<(), Self::Error> {
Ok(())
}
fn decode_object_identifier(&mut self, _: Tag) -> Result<ObjectIdentifier, Self::Error> {
let length = self.decode_length()?;
let ber_decoder = crate::ber::de::Decoder::new(&[], crate::ber::de::DecoderOptions::ber());
ber_decoder.decode_object_identifier_from_bytes(self.extract_data_by_length(length)?)
}
fn decode_sequence<const RC: usize, const EC: usize, D, DF: FnOnce() -> D, F>(
&mut self,
_: Tag,
default_initializer_fn: Option<DF>,
decode_fn: F,
) -> Result<D, Self::Error>
where
D: Constructed<RC, EC>,
F: FnOnce(&mut Self::AnyDecoder<RC, EC>) -> Result<D, Self::Error>,
{
self.check_recursion_depth()?;
if D::FIELDS.is_empty()
|| D::FIELDS.len() == D::FIELDS.number_of_optional_and_default_fields()
&& self.input.is_empty()
{
if let Some(default_initializer_fn) = default_initializer_fn {
return Ok((default_initializer_fn)());
}
return Err(DecodeError::from_kind(
DecodeErrorKind::UnexpectedEmptyInput,
self.codec(),
));
}
let (bitmap, extensible_present) = self.parse_preamble::<RC, EC, D>()?;
let mut fields = ([None; RC], 0);
D::FIELDS
.optional_and_default_fields()
.zip(bitmap)
.enumerate()
.for_each(|(i, (field, is_present))| {
if is_present {
fields.0[i] = Some(field);
} else {
fields.0[i] = None;
}
});
let value = {
let mut sequence_decoder = Decoder::new(self.input, self.options);
sequence_decoder.options.remaining_depth =
sequence_decoder.options.remaining_depth.saturating_sub(1);
sequence_decoder.extension_fields = D::EXTENDED_FIELDS;
sequence_decoder.extensions_present = extensible_present.then_some(None);
sequence_decoder.fields = fields;
let value = decode_fn(&mut sequence_decoder)?;
self.input = sequence_decoder.input;
value
};
Ok(value)
}
fn decode_sequence_of<D: Decode>(
&mut self,
_: Tag,
_: Constraints,
) -> Result<Vec<D>, Self::Error> {
self.check_recursion_depth()?;
let length_of_quantity = self.decode_length()?;
let coer = self.options.encoding_rules.is_coer();
let length_bytes = self.extract_data_by_length(length_of_quantity)?;
if coer && length_bytes.first() == Some(&0) && length_bytes.len() > 1 {
return Err(CoerDecodeErrorKind::NotValidCanonicalEncoding {
msg: "Quantity value in 'sequence/set of' should not have leading zeroes in COER"
.to_string(),
}
.into());
}
let length = usize::try_from_unsigned_bytes(length_bytes, self.codec())?;
let mut sequence_of: Vec<D> = Vec::with_capacity(length);
let mut options = self.options;
options.remaining_depth = options.remaining_depth.saturating_sub(1);
let mut decoder = Self::new(self.input, options);
for _ in 0..length {
let value = D::decode(&mut decoder)?;
self.input = decoder.input;
sequence_of.push(value);
}
Ok(sequence_of)
}
fn decode_set_of<D: Decode + Eq + core::hash::Hash>(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<SetOf<D>, Self::Error> {
self.decode_sequence_of(tag, constraints)
.map(|seq| SetOf::from_vec(seq))
}
fn decode_octet_string<'b, T: From<&'b [u8]> + From<Vec<u8>>>(
&'b mut self,
_: Tag,
constraints: Constraints,
) -> Result<T, Self::Error> {
if let Some(size) = constraints.size() {
if size.constraint.is_fixed() && size.extensible.is_none() {
let data =
self.extract_data_by_length(*size.constraint.as_start().ok_or_else(|| {
DecodeError::size_constraint_not_satisfied(
None,
"Fixed size constraint should have value when decoding Octet String"
.to_string(),
self.codec(),
)
})?)?;
return Ok(T::from(data));
}
}
let length = self.decode_length()?;
let data = self.extract_data_by_length(length)?;
Ok(T::from(data))
}
fn decode_utf8_string(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<String, Self::Error> {
self.decode_octet_string(tag, constraints)
.and_then(|bytes| {
String::from_utf8(bytes).map_err(|e| {
DecodeError::string_conversion_failed(
Tag::UTF8_STRING,
e.to_string(),
self.codec(),
)
})
})
}
fn decode_visible_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<VisibleString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_general_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<GeneralString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_graphic_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<GraphicString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_ia5_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<Ia5String, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_printable_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<PrintableString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_numeric_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<NumericString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_teletex_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<TeletexString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_bmp_string(
&mut self,
_: Tag,
constraints: Constraints,
) -> Result<BmpString, Self::Error> {
self.parse_known_multiplier_string(&constraints)
}
fn decode_optional_with_explicit_prefix<D: Decode>(
&mut self,
tag: Tag,
) -> Result<Option<D>, Self::Error> {
self.decode_optional_with_tag(tag)
}
fn decode_explicit_prefix<D: Decode>(&mut self, tag: Tag) -> Result<D, Self::Error> {
if D::IS_CHOICE {
D::decode(self)
} else {
D::decode_with_tag(self, tag)
}
}
fn decode_utc_time(&mut self, tag: Tag) -> Result<UtcTime, Self::Error> {
let string = String::from_utf8(self.decode_octet_string(tag, Constraints::default())?)
.map_err(|_| {
DecodeError::string_conversion_failed(
Tag::UTF8_STRING,
"UTCTime should be UTF8 encoded.".to_string(),
self.codec(),
)
})?;
crate::der::de::Decoder::parse_canonical_utc_time_string(&string)
}
fn decode_generalized_time(&mut self, tag: Tag) -> Result<GeneralizedTime, Self::Error> {
let string = String::from_utf8(self.decode_octet_string(tag, Constraints::default())?)
.map_err(|_| {
DecodeError::string_conversion_failed(
Tag::UTF8_STRING,
"GeneralizedTime should be UTF8 encoded".to_string(),
self.codec(),
)
})?;
crate::der::de::Decoder::parse_canonical_generalized_time_string(string)
}
fn decode_date(&mut self, tag: Tag) -> Result<types::Date, Self::Error> {
let string = String::from_utf8(self.decode_octet_string(tag, Constraints::default())?)
.map_err(|_| {
DecodeError::string_conversion_failed(
Tag::UTF8_STRING,
"DATE should be UTF8 encoded".to_string(),
self.codec(),
)
})?;
crate::der::de::Decoder::parse_date_string(&string)
}
fn decode_set<const RC: usize, const EC: usize, FIELDS, SET, D, F>(
&mut self,
_: Tag,
decode_fn: D,
field_fn: F,
) -> Result<SET, Self::Error>
where
SET: Decode + Constructed<RC, EC>,
FIELDS: Decode,
D: Fn(&mut Self::AnyDecoder<RC, EC>, usize, Tag) -> Result<FIELDS, Self::Error>,
F: FnOnce(Vec<FIELDS>) -> Result<SET, Self::Error>,
{
self.check_recursion_depth()?;
let (bitmap, extensible_present) = self.parse_preamble::<RC, EC, SET>()?;
let mut field_map: ([Option<Field>; RC], usize) = ([None; RC], 0);
for (i, (field, is_present)) in SET::FIELDS
.canonised()
.optional_and_default_fields()
.zip(bitmap)
.enumerate()
{
if is_present {
field_map.0[i] = Some(field);
} else {
field_map.0[i] = None;
}
}
let fields = {
let extended_fields_len = SET::EXTENDED_FIELDS.map_or(0, |fields| fields.len());
let mut fields = Vec::with_capacity(SET::FIELDS.len() + extended_fields_len);
let mut set_decoder = Decoder::new(self.input, self.options);
set_decoder.options.remaining_depth =
set_decoder.options.remaining_depth.saturating_sub(1);
set_decoder.extension_fields = SET::EXTENDED_FIELDS;
set_decoder.extensions_present = extensible_present.then_some(None);
set_decoder.fields = field_map;
let mut opt_index = 0;
for field in SET::FIELDS.canonised().iter() {
if field.is_optional_or_default() {
if field_map.0.get(opt_index).unwrap().is_some() {
fields.push(decode_fn(&mut set_decoder, field.index, field.tag)?);
}
opt_index += 1;
} else {
fields.push(decode_fn(&mut set_decoder, field.index, field.tag)?);
}
}
for (indice, field) in SET::EXTENDED_FIELDS
.iter()
.flat_map(Fields::iter)
.enumerate()
{
fields.push(decode_fn(
&mut set_decoder,
indice + SET::FIELDS.len(),
field.tag,
)?);
}
self.input = set_decoder.input;
fields
};
field_fn(fields)
}
fn decode_choice<D>(&mut self, constraints: Constraints) -> Result<D, Self::Error>
where
D: DecodeChoice,
{
self.check_recursion_depth()?;
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(&[]));
if is_root_extension {
self.options.remaining_depth = self.options.remaining_depth.saturating_sub(1);
let result = D::from_tag(self, tag);
self.options.remaining_depth = self.options.remaining_depth.saturating_add(1);
result
} else if is_extensible && is_extended_extension {
let length = self.decode_length()?;
let bytes = self.extract_data_by_length(length)?;
let mut decoder = Decoder::<0, 0>::new(bytes, self.options);
decoder.options.remaining_depth = decoder.options.remaining_depth.saturating_sub(1);
D::from_tag(&mut decoder, tag)
} else {
Err(OerDecodeErrorKind::invalid_tag_variant_on_choice(
tag,
is_extensible,
))
}
}
fn decode_optional<D: Decode>(&mut self) -> Result<Option<D>, Self::Error> {
self.decode_optional_with_tag(D::TAG)
}
fn decode_optional_with_tag<D: Decode>(&mut self, tag: Tag) -> Result<Option<D>, Self::Error> {
let is_present = self.require_field(tag)?;
if is_present {
D::decode_with_tag(self, tag).map(Some)
} else {
Ok(None)
}
}
fn decode_optional_with_constraints<D: Decode>(
&mut self,
constraints: Constraints,
) -> Result<Option<D>, Self::Error> {
let is_present = self.require_field(D::TAG)?;
if is_present {
D::decode_with_constraints(self, constraints).map(Some)
} else {
Ok(None)
}
}
fn decode_optional_with_tag_and_constraints<D: Decode>(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<Option<D>, Self::Error> {
let is_present = self.require_field(tag)?;
if is_present {
D::decode_with_tag_and_constraints(self, tag, constraints).map(Some)
} else {
Ok(None)
}
}
fn decode_extension_addition_with_explicit_tag_and_constraints<D>(
&mut self,
tag: Tag,
constraints: Constraints,
) -> Result<Option<D>, Self::Error>
where
D: Decode,
{
self.decode_extension_addition_with_tag_and_constraints::<D>(tag, constraints)
}
fn decode_extension_addition_with_tag_and_constraints<D>(
&mut self,
_tag: Tag,
constraints: Constraints,
) -> Result<Option<D>, Self::Error>
where
D: Decode,
{
if !self.parse_extension_header()? {
return Ok(None);
}
let extension_is_present = self.extension_is_present()?.is_some();
if !extension_is_present {
return Ok(None);
}
let options = self.options;
let bytes: Cow<[u8]> =
self.decode_octet_string(Tag::OCTET_STRING, Constraints::default())?;
let mut decoder = Decoder::<0, 0>::new(&bytes, options);
D::decode_with_constraints(&mut decoder, constraints).map(Some)
}
fn decode_extension_addition_group<
const RC: usize,
const EC: usize,
D: Decode + Constructed<RC, EC>,
>(
&mut self,
) -> Result<Option<D>, Self::Error> {
if !self.parse_extension_header()? {
return Ok(None);
}
let extension_is_present = self.extension_is_present()?.is_some();
if !extension_is_present {
return Ok(None);
}
let options = self.options;
let bytes: Cow<[u8]> =
self.decode_octet_string(Tag::OCTET_STRING, Constraints::default())?;
let mut decoder = Decoder::<0, 0>::new(&bytes, options);
D::decode(&mut decoder).map(Some)
}
}
#[cfg(test)]
#[allow(clippy::assertions_on_constants)]
mod tests {
use num_bigint::BigUint;
const MAX_LENGTH: [u8; 127] = [0xff; 127];
const MAX_LENGTH_LENGTH: usize = MAX_LENGTH.len();
use super::*;
use crate::types::constraints::Constraints;
use bitvec::prelude::BitSlice;
use num_bigint::BigInt;
#[test]
fn test_decode_bool() {
let decoded: bool = crate::oer::decode(&[0xffu8]).unwrap();
assert!(decoded);
let decoded: bool = crate::oer::decode(&[0u8]).unwrap();
assert!(!decoded);
let decoded: bool = crate::oer::decode(&[0xffu8, 0xff]).unwrap();
assert!(decoded);
let decoded: bool = crate::oer::decode(&[0x33u8, 0x0]).unwrap();
assert!(decoded);
}
#[test]
fn test_decode_length_invalid() {
let data = &[0xffu8];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
assert!(decoder.decode_length().is_err());
let data = &[0xffu8, 0xff];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
assert!(decoder.decode_length().is_err());
}
#[test]
fn test_decode_length_valid() {
let max_length: BigUint = BigUint::from(2u8).pow(1016u32) - BigUint::from(1u8);
assert_eq!(max_length.to_bytes_be(), MAX_LENGTH);
assert_eq!(max_length.to_bytes_be().len(), MAX_LENGTH_LENGTH);
assert!(max_length > usize::MAX.into());
assert!(usize::MAX > BitSlice::<usize>::MAX_BITS);
let data = &[0x01u8, 0xff];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
assert_eq!(decoder.decode_length().unwrap(), 1);
let data = &[0x03u8, 0xff, 0xff, 0xfe];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
assert_eq!(decoder.decode_length().unwrap(), 3);
let mut data: [u8; 0x80] = [0xffu8; 0x80];
data[0] = 0x7f; let data = &data;
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
assert_eq!(decoder.decode_length().unwrap(), 127);
let length: [u8; 1] = [0x82u8]; let length_determinant: [u8; 0x02] = [0x01u8, 0x02];
let data: [u8; 258] = [0xffu8; 258];
let mut combined: [u8; 261] = [0x0; 261];
combined[..1].copy_from_slice(&length);
combined[1..=2].copy_from_slice(&length_determinant);
combined[3..].copy_from_slice(&data);
let data = &combined;
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
assert_eq!(decoder.decode_length().unwrap(), 258usize);
}
#[test]
fn test_long_form_length_decode() {
let vc = &[
0x81, 0x80, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
];
let mut decoder = Decoder::<0, 0>::new(vc, DecoderOptions::oer());
let number = BigInt::from(256).pow(127) - 1;
let constraints = Constraints::default();
let new_number: BigInt = decoder
.decode_integer_with_constraints(&constraints)
.unwrap();
assert_eq!(new_number, number);
let length: [u8; 1] = [0x80u8 + u8::try_from(usize::BITS / 8u32).unwrap()]; let length_determinant: [u8; (usize::BITS / 8u32) as usize] =
[0xff; (usize::BITS / 8u32) as usize];
let mut combined: [u8; 1 + (usize::BITS / 8u32) as usize] =
[0x0; 1 + (usize::BITS / 8u32) as usize];
combined[..1].copy_from_slice(&length);
combined[1..=(usize::BITS / 8u32) as usize].copy_from_slice(&length_determinant);
let data = &combined;
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
let new_length = decoder.decode_length().unwrap();
assert_eq!(new_length, usize::MAX);
let length: [u8; 1] = [0x80u8 + u8::try_from(usize::BITS / 8u32).unwrap() + 1]; let length_determinant: [u8; (usize::BITS / 8u32) as usize + 1] =
[0xff; (usize::BITS / 8u32) as usize + 1];
let mut combined: [u8; 1 + (usize::BITS / 8u32) as usize + 1] =
[0x0; 1 + (usize::BITS / 8u32) as usize + 1];
combined[..1].copy_from_slice(&length);
combined[1..=(usize::BITS / 8u32 + 1) as usize].copy_from_slice(&length_determinant);
let data = &combined;
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
let new_length = decoder.decode_length();
assert!(new_length.is_err());
}
#[test]
fn test_integer_decode_with_constraints() {
const CONSTRAINT_1: Constraints = constraints!(value_constraint!(0, 255));
let data = &[0x01u8];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
let decoded_int: i32 = decoder
.decode_integer_with_constraints(&CONSTRAINT_1)
.unwrap();
assert_eq!(decoded_int, 1);
let data = &[0xffu8];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
let decoded_int: i64 = decoder
.decode_integer_with_constraints(&CONSTRAINT_1)
.unwrap();
assert_eq!(decoded_int, 255);
let data = &[0xffu8, 0xff];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
let decoded_int: BigInt = decoder
.decode_integer_with_constraints(&CONSTRAINT_1)
.unwrap();
assert_eq!(decoded_int, 255.into());
let data = &[0x02u8, 0xff, 0x01];
let mut decoder = Decoder::<0, 0>::new(data, DecoderOptions::oer());
const CONSTRAINT_2: Constraints = Constraints::default();
let decoded_int: BigInt = decoder
.decode_integer_with_constraints(&CONSTRAINT_2)
.unwrap();
assert_eq!(decoded_int, BigInt::from(-255));
}
}