use alloc::vec::Vec;
use bitvec::prelude::*;
use num_traits::ToPrimitive;
use crate::{
Codec, Encode,
oer::EncodingRules,
types::{
Any, BitStr, BmpString, Choice, Constraints, Constructed, Date, Enumerated, GeneralString,
GeneralizedTime, GraphicString, Ia5String, Identifier, IntegerType, NumericString,
PrintableString, RealType, SetOf, Tag, TeletexString, UtcTime, VisibleString,
},
};
use crate::error::{CoerEncodeErrorKind, EncodeError, EncodeErrorKind};
pub const ITU_T_X696_OER_EDITION: f32 = 3.0;
#[derive(Clone, Copy, Debug)]
pub struct EncoderOptions {
encoding_rules: EncodingRules,
set_encoding: bool,
}
impl EncoderOptions {
#[must_use]
pub const fn coer() -> Self {
Self {
encoding_rules: EncodingRules::Coer,
set_encoding: false,
}
}
fn without_set_encoding(mut self) -> Self {
self.set_encoding = false;
self
}
#[must_use]
fn current_codec(self) -> Codec {
match self.encoding_rules {
EncodingRules::Oer => Codec::Oer,
EncodingRules::Coer => Codec::Coer,
}
}
}
impl Default for EncoderOptions {
fn default() -> Self {
Self::coer()
}
}
#[derive(Debug, Clone, Copy)]
struct ConstructedCursor<const RC: usize, const EC: usize> {
number_optional_default: usize,
preamble_width: usize,
preamble_cursor: usize,
extension_missing_bits: u8,
extension_bitfield_width: usize,
extension_bitmap_width: usize,
extension_bitmap_total_width: usize,
extension_bitmap_cursor: usize,
}
impl<const RC: usize, const EC: usize> ConstructedCursor<RC, EC> {
const fn new(number_optional_default: usize, is_extensible: bool) -> Self {
let preamble_missing_bits =
(8 - ((is_extensible as usize + number_optional_default) & 7)) & 7;
debug_assert!(
(preamble_missing_bits + is_extensible as usize + number_optional_default)
.is_multiple_of(8)
);
let preamble_width =
(number_optional_default + is_extensible as usize + preamble_missing_bits) / 8;
let extension_missing_bits: u8 =
((EC > 0) as u8).wrapping_neg() & ((8 - (EC & 7) as u8) & 7);
debug_assert!((EC + extension_missing_bits as usize).is_multiple_of(8));
let extension_bitfield_width = (EC + extension_missing_bits as usize) / 8;
let extension_bitmap_width = 1 + extension_bitfield_width;
let extension_bitmap_width_length = if extension_bitmap_width <= 127 {
1 } else {
1 + (extension_bitmap_width as u32).ilog2().div_ceil(8) as usize };
let extension_bitmap_total_width = extension_bitmap_width + extension_bitmap_width_length;
Self {
number_optional_default,
preamble_width,
preamble_cursor: 0,
extension_missing_bits,
extension_bitfield_width,
extension_bitmap_width,
extension_bitmap_total_width,
extension_bitmap_cursor: 0,
}
}
fn set_extension_bitmap_cursor(&mut self, cursor: usize) {
self.extension_bitmap_cursor = cursor;
}
fn set_preamble_cursor(&mut self, cursor: usize) {
self.preamble_cursor = cursor;
}
const fn default() -> Self {
Self {
number_optional_default: 0,
preamble_width: 0,
preamble_cursor: 0,
extension_bitfield_width: 0,
extension_bitmap_width: 0,
extension_missing_bits: 0,
extension_bitmap_total_width: 0,
extension_bitmap_cursor: 0,
}
}
}
#[derive(Debug)]
pub struct Encoder<'buffer, const RCL: usize = 0, const ECL: usize = 0> {
options: EncoderOptions,
output: &'buffer mut Vec<u8>,
set_output: alloc::collections::BTreeMap<Tag, Vec<u8>>,
is_extension_sequence: bool,
root_bitfield: (usize, [(bool, Tag); RCL]),
extension_bitfield: (usize, [bool; ECL]),
cursor: ConstructedCursor<RCL, ECL>,
worker: &'buffer mut Vec<u8>,
}
impl<'buffer, const RCL: usize, const ECL: usize> Encoder<'buffer, RCL, ECL> {
#[must_use]
pub fn from_buffer(
options: EncoderOptions,
output: &'buffer mut Vec<u8>,
worker: &'buffer mut Vec<u8>,
) -> Self {
Self {
options,
output,
set_output: <_>::default(),
root_bitfield: (0, [(false, Tag::new_private(0)); RCL]),
extension_bitfield: (0, [false; ECL]),
cursor: ConstructedCursor::default(),
is_extension_sequence: bool::default(),
worker,
}
}
fn codec(&self) -> Codec {
self.options.current_codec()
}
#[must_use]
pub fn output(&mut self) -> Vec<u8> {
core::mem::take(self.output)
}
fn collect_set(&mut self) {
self.output.append(
self.set_output
.values()
.flatten()
.copied()
.collect::<Vec<u8>>()
.as_mut(),
);
}
fn set_presence(&mut self, tag: Tag, bit: bool) {
if RCL > 0 {
if self.cursor.number_optional_default < self.root_bitfield.0 + 1 {
return;
}
self.root_bitfield.1[self.root_bitfield.0] = (bit, tag);
self.root_bitfield.0 += 1;
}
}
fn set_extension_presence(&mut self, bit: bool) {
if ECL > 0 {
self.extension_bitfield.1[self.extension_bitfield.0] = bit;
self.extension_bitfield.0 += 1;
}
}
fn extend(&mut self, tag: Tag) {
if self.options.set_encoding {
self.set_output.insert(tag, core::mem::take(self.output));
}
}
fn encode_tag(&self, tag: Tag, bv: &mut BitSlice<u8, Msb0>) -> usize {
use crate::types::Class;
let mut index = 0;
match tag.class {
Class::Universal => {
bv.set(index, false);
bv.set(index + 1, false);
index += 2;
}
Class::Application => {
bv.set(index, false);
bv.set(index + 1, true);
index += 2;
}
Class::Context => {
bv.set(index, true);
bv.set(index + 1, false);
index += 2;
}
Class::Private => {
bv.set(index, true);
bv.set(index + 1, true);
index += 2;
}
}
let mut tag_number = tag.value;
if tag_number < 63 {
for i in (0..6).rev() {
bv.set(index, tag_number & (1 << i) != 0);
index += 1;
}
} else {
for i in 0..6 {
bv.set(index + i, true);
}
index += 6;
let mut tag_number_bits = 0;
let mut temp_tag_number = tag_number;
while temp_tag_number > 0 {
temp_tag_number >>= 1;
tag_number_bits += 1;
}
let mut remainer = 7 - tag_number_bits % 7;
bv.set(index, true);
index += 1;
for _ in 0..7 {
if remainer != 0 {
bv.set(index, false);
index += 1;
remainer -= 1;
continue;
}
bv.set(index, tag_number & 1 != 0);
tag_number >>= 1;
index += 1;
}
while tag_number > 0 {
bv.set(index, true);
index += 1;
for _ in 0..7 {
bv.set(index, tag_number & 1 != 0);
tag_number >>= 1;
index += 1;
}
}
let bv_last_8bit = &bv[..index].len() - 8;
bv.replace(bv_last_8bit, false);
debug_assert!(&bv[2..8].all());
debug_assert!(&bv[9..16].any());
}
index
}
fn encode_unconstrained_enum_index(&mut self, value: isize) -> Result<(), EncodeError> {
let (bytes, needed) = value.to_signed_bytes_be();
let mut length = u8::try_from(needed).map_err(|err| {
EncodeError::integer_type_conversion_failed(
alloc::format!(
"Length of length conversion failed when encoding enumerated index.\
value likely too large: {err}"
),
self.codec(),
)
})?;
if length > 127 {
return Err(CoerEncodeErrorKind::TooLongValue {
length: needed as u128,
}
.into());
}
length |= 0b_1000_0000;
self.output.extend_from_slice(&length.to_be_bytes());
self.output.extend_from_slice(&bytes.as_ref()[..needed]);
Ok(())
}
fn encode_length(buffer: &mut Vec<u8>, length: usize) -> Result<(), EncodeError> {
let (bytes, needed) = length.to_unsigned_bytes_be();
if length < 128 {
buffer.extend_from_slice(&bytes.as_ref()[..needed]);
return Ok(());
}
let mut length_of_length = u8::try_from(needed).map_err(|err| {
EncodeError::integer_type_conversion_failed(
alloc::format!("Length of length conversion failed: {err}"),
Codec::Coer,
)
})?;
if length_of_length > 127 {
return Err(CoerEncodeErrorKind::TooLongValue {
length: length as u128,
}
.into());
}
length_of_length |= 0b_1000_0000;
buffer.extend_from_slice(&length_of_length.to_be_bytes());
buffer.extend_from_slice(&bytes.as_ref()[..needed]);
Ok(())
}
fn encode_unconstrained_integer<I: IntegerType>(
&mut self,
value_to_enc: &I,
signed: bool,
) -> Result<(), EncodeError> {
if signed {
let (bytes, needed) = value_to_enc.to_signed_bytes_be();
Self::encode_length(self.output, needed)?;
self.output.extend_from_slice(&bytes.as_ref()[..needed]);
} else {
let (bytes, needed) = value_to_enc.to_unsigned_bytes_be();
Self::encode_length(self.output, needed)?;
self.output.extend_from_slice(&bytes.as_ref()[..needed]);
};
Ok(())
}
fn encode_integer_with_constraints<I: IntegerType>(
&mut self,
tag: Tag,
constraints: &Constraints,
value_to_enc: &I,
) -> Result<(), EncodeError> {
if let Some(value) = constraints.value() {
if !value.constraint.value.in_bound(value_to_enc) && value.extensible.is_none() {
return Err(EncodeError::value_constraint_not_satisfied(
value_to_enc.to_bigint().unwrap_or_default(),
&value.constraint.value,
self.codec(),
));
}
let (signed, octets) = if value.extensible.is_some() {
(true, None)
} else {
(value.constraint.get_sign(), value.constraint.get_range())
};
if let Some(octets) = octets {
self.encode_constrained_integer_with_padding(
usize::from(octets),
value_to_enc,
signed,
)?;
} else {
self.encode_unconstrained_integer(value_to_enc, signed)?;
}
} else {
self.encode_unconstrained_integer(value_to_enc, true)?;
}
self.extend(tag);
Ok(())
}
fn encode_constrained_integer_with_padding<I: IntegerType>(
&mut self,
octets: usize,
value: &I,
signed: bool,
) -> Result<(), EncodeError> {
use core::cmp::Ordering;
if octets > 8 {
return Err(CoerEncodeErrorKind::InvalidConstrainedIntegerOctetSize.into());
}
let signed_ref;
let unsigned_ref;
let needed: usize;
let bytes = if signed {
(signed_ref, needed) = value.to_signed_bytes_be();
signed_ref.as_ref()
} else {
(unsigned_ref, needed) = value.to_unsigned_bytes_be();
unsigned_ref.as_ref()
};
match octets.cmp(&needed) {
Ordering::Greater => {
const PADDED_BYTES_NEG: [u8; 8] = [0xffu8; 8];
const PADDED_BYTES_POS: [u8; 8] = [0x00u8; 8];
let idx = usize::from(signed && value.is_negative());
let padded_bytes = [&PADDED_BYTES_POS, &PADDED_BYTES_NEG][idx];
self.output
.extend_from_slice(&padded_bytes[..octets - needed]);
}
Ordering::Less => {
return Err(EncodeError::from_kind(
EncodeErrorKind::MoreBytesThanExpected {
value: needed,
expected: octets,
},
self.codec(),
));
}
Ordering::Equal => {}
};
self.output.extend_from_slice(&bytes[..needed]);
Ok(())
}
fn check_fixed_size_constraint(
&self,
length: usize,
constraints: &Constraints,
) -> Result<bool, EncodeError> {
if let Some(size) = constraints.size() {
if !size.constraint.contains(&length) && size.extensible.is_none() {
return Err(EncodeError::size_constraint_not_satisfied(
length,
&size.constraint,
self.codec(),
));
}
if size.constraint.is_fixed() && size.extensible.is_none() {
return Ok(true);
}
}
const MAX_PERMITTED_LENGTH: usize = usize::MAX / 8;
if length > MAX_PERMITTED_LENGTH {
return Err(EncodeError::length_exceeds_platform_size(self.codec()));
}
Ok(false)
}
fn extension_bitmap_reserve(&mut self) {
self.cursor.set_extension_bitmap_cursor(self.output.len());
self.output.extend(core::iter::repeat_n(
0,
self.cursor.extension_bitmap_total_width,
));
}
fn encode_constructed<const RC: usize, const EC: usize, C: Constructed<RC, EC>>(
&mut self,
tag: Tag,
set_output: Option<&mut alloc::collections::BTreeMap<Tag, Vec<u8>>>,
) -> Result<(), EncodeError> {
let mut preamble = BitArray::<[u8; RC], Msb0>::default();
let mut preamble_index = 0;
let mut extensions_present = false;
if C::IS_EXTENSIBLE {
extensions_present = self.extension_bitfield.1.iter().any(|b| *b);
if RC > 0 {
preamble.set(0, extensions_present);
preamble_index += 1;
}
}
let (needed, option_bitfield) = if self.options.set_encoding {
self.root_bitfield
.1
.sort_by(|(_, tag1), (_, tag2)| tag1.const_cmp(tag2));
self.root_bitfield
} else {
self.root_bitfield
};
debug_assert!(C::FIELDS.number_of_optional_and_default_fields() == needed);
for (bit, _tag) in &option_bitfield[..needed] {
preamble.set(preamble_index, *bit);
preamble_index += 1;
}
if needed > 0 || C::IS_EXTENSIBLE {
if RC == 0 && C::IS_EXTENSIBLE {
self.output.push(u8::from(extensions_present) << 7);
} else {
if self.options.set_encoding {
self.output
.extend_from_slice(&preamble.as_raw_slice()[..self.cursor.preamble_width]);
} else {
self.output[self.cursor.preamble_cursor
..self.cursor.preamble_cursor + self.cursor.preamble_width]
.copy_from_slice(&preamble.as_raw_slice()[..self.cursor.preamble_width]);
}
}
}
if !C::IS_EXTENSIBLE || !extensions_present {
if let Some(set_output) = set_output {
set_output.insert(tag, core::mem::take(self.output));
}
return Ok(());
}
debug_assert_ne!(self.cursor.extension_bitmap_cursor, 0);
let mut extension_bitmap_buffer: BitArray<[u8; EC], Msb0> = BitArray::default();
Self::encode_length(self.worker, self.cursor.extension_bitmap_width)?;
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());
cursor += 1;
for (i, bit) in self.extension_bitfield.1.iter().enumerate() {
extension_bitmap_buffer.set(i, *bit);
}
self.output[cursor..cursor + self.cursor.extension_bitfield_width].copy_from_slice(
&extension_bitmap_buffer.as_raw_slice()[..self.cursor.extension_bitfield_width],
);
if let Some(set_output) = set_output {
set_output.insert(tag, core::mem::take(self.output));
}
Ok(())
}
}
impl<'buffer, const RFC: usize, const EFC: usize> crate::Encoder<'buffer>
for Encoder<'buffer, RFC, EFC>
{
type Ok = ();
type Error = EncodeError;
type AnyEncoder<'this, const R: usize, const E: usize> = Encoder<'this, R, E>;
fn codec(&self) -> Codec {
self.options.current_codec()
}
fn encode_any(
&mut self,
tag: Tag,
value: &Any,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(
tag,
<Constraints>::default(),
value.as_bytes(),
Identifier::EMPTY,
)
}
fn encode_bool(
&mut self,
tag: Tag,
value: bool,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.output
.extend_from_slice(if value { &[0xffu8] } else { &[0x00u8] });
self.extend(tag);
Ok(())
}
fn encode_bit_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &BitStr,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
let mut bit_string_encoding = BitVec::<u8, Msb0>::with_capacity(value.len());
if let Some(size) = constraints.size() {
if size.constraint.is_fixed() && size.extensible.is_none() {
if size.constraint.contains(&value.len()) {
let missing_bits: usize = (8 - (value.len() & 7)) & 7;
bit_string_encoding.extend(value);
if missing_bits > 0 {
bit_string_encoding.extend(core::iter::repeat_n(false, missing_bits));
}
self.output
.extend_from_slice(bit_string_encoding.as_raw_slice());
} else {
return Err(EncodeError::size_constraint_not_satisfied(
value.len(),
&size.constraint,
self.codec(),
));
}
self.extend(tag);
return Ok(());
}
}
if value.is_empty() {
Self::encode_length(self.output, 1)?;
self.output.extend_from_slice(&[0x00u8]);
} else {
let missing_bits: usize = (8 - value.len() % 8) % 8;
let trailing = [false; 8];
let trailing = &trailing[..missing_bits];
bit_string_encoding.extend(missing_bits.to_u8().unwrap_or(0).to_be_bytes());
bit_string_encoding.extend(value);
bit_string_encoding.extend(trailing);
Self::encode_length(self.output, bit_string_encoding.len() / 8)?;
self.output
.extend_from_slice(bit_string_encoding.as_raw_slice());
}
self.extend(tag);
Ok(())
}
fn encode_enumerated<E: Enumerated>(
&mut self,
tag: Tag,
value: &E,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
let number = value.discriminant();
if 0isize <= number && number <= i8::MAX.into() {
self.encode_constrained_integer_with_padding(1, &number, false)?;
} else {
self.encode_unconstrained_enum_index(number)?;
}
self.extend(tag);
Ok(())
}
fn encode_object_identifier(
&mut self,
tag: Tag,
value: &[u32],
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
let mut enc = crate::ber::enc::Encoder::new(crate::ber::enc::EncoderOptions::ber());
let mut octets = enc.object_identifier_as_bytes(value)?;
Self::encode_length(self.output, octets.len())?;
self.output.append(&mut octets);
self.extend(tag);
Ok(())
}
fn encode_integer<I: IntegerType>(
&mut self,
tag: Tag,
constraints: Constraints,
value: &I,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_integer_with_constraints(tag, &constraints, value)
}
fn encode_real<R: RealType>(
&mut self,
tag: Tag,
_constraints: Constraints,
value: &R,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
let (bytes, len) = value.to_ieee754_bytes();
self.output.extend_from_slice(&bytes.as_ref()[..len]);
self.extend(tag);
Ok(())
}
fn encode_null(&mut self, _tag: Tag, _: Identifier) -> Result<Self::Ok, Self::Error> {
Ok(())
}
fn encode_octet_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &[u8],
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
if self.check_fixed_size_constraint(value.len(), &constraints)? {
self.output.extend_from_slice(value);
} else {
Self::encode_length(self.output, value.len())?;
self.output.extend_from_slice(value);
}
self.extend(tag);
Ok(())
}
fn encode_general_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &GeneralString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value, Identifier::EMPTY)
}
fn encode_graphic_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &GraphicString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value, Identifier::EMPTY)
}
fn encode_utf8_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &str,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value.as_bytes(), Identifier::EMPTY)
}
fn encode_visible_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &VisibleString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value.as_iso646_bytes(), Identifier::EMPTY)
}
fn encode_ia5_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &Ia5String,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value.as_iso646_bytes(), Identifier::EMPTY)
}
fn encode_printable_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &PrintableString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value.as_bytes(), Identifier::EMPTY)
}
fn encode_numeric_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &NumericString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, value.as_bytes(), Identifier::EMPTY)
}
fn encode_teletex_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &TeletexString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, &value.to_bytes(), Identifier::EMPTY)
}
fn encode_bmp_string(
&mut self,
tag: Tag,
constraints: Constraints,
value: &BmpString,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(tag, constraints, &value.to_bytes(), Identifier::EMPTY)
}
fn encode_generalized_time(
&mut self,
tag: Tag,
value: &GeneralizedTime,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(
tag,
Constraints::default(),
&crate::der::enc::Encoder::datetime_to_canonical_generalized_time_bytes(value),
Identifier::EMPTY,
)
}
fn encode_utc_time(
&mut self,
tag: Tag,
value: &UtcTime,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(
tag,
Constraints::default(),
&crate::der::enc::Encoder::datetime_to_canonical_utc_time_bytes(value),
Identifier::EMPTY,
)
}
fn encode_date(
&mut self,
tag: Tag,
value: &Date,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_octet_string(
tag,
Constraints::default(),
&crate::der::enc::Encoder::naivedate_to_date_bytes(value),
Identifier::EMPTY,
)
}
fn encode_explicit_prefix<V: Encode>(
&mut self,
tag: Tag,
value: &V,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
if V::IS_CHOICE {
value.encode(self)
} else {
value.encode_with_tag(self, tag)
}
}
fn encode_sequence<'b, const RL: usize, const EL: usize, C, F>(
&'b mut self,
tag: Tag,
encoder_scope: F,
_: Identifier,
) -> Result<Self::Ok, Self::Error>
where
C: Constructed<RL, EL>,
F: FnOnce(&mut Self::AnyEncoder<'b, RL, EL>) -> Result<(), Self::Error>,
{
let mut encoder = Encoder::<'_, RL, EL>::from_buffer(
self.options.without_set_encoding(),
self.output,
self.worker,
);
let mut cursor = ConstructedCursor::<RL, EL>::new(
C::FIELDS.number_of_optional_and_default_fields(),
C::IS_EXTENSIBLE,
);
cursor.set_preamble_cursor(encoder.output.len());
for _ in 0..cursor.preamble_width {
encoder.output.push(0);
}
encoder.cursor = cursor;
encoder_scope(&mut encoder)?;
if self.options.set_encoding {
encoder.encode_constructed::<RL, EL, C>(tag, Some(&mut self.set_output))?;
} else {
encoder.encode_constructed::<RL, EL, C>(tag, None)?;
}
Ok(())
}
fn encode_sequence_of<E: Encode>(
&mut self,
tag: Tag,
value: &[E],
_: Constraints,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_unconstrained_integer(&value.len(), false)?;
self.output.reserve(core::mem::size_of_val(value));
let mut encoder = Encoder::<0>::from_buffer(self.options, self.output, self.worker);
{
for one in value {
E::encode(one, &mut encoder)?;
}
}
self.extend(tag);
Ok(())
}
fn encode_set<'b, const RL: usize, const EL: usize, C, F>(
&'b mut self,
tag: Tag,
encoder_scope: F,
_: Identifier,
) -> Result<Self::Ok, Self::Error>
where
C: Constructed<RL, EL>,
F: FnOnce(&mut Self::AnyEncoder<'b, RL, EL>) -> Result<(), Self::Error>,
{
let mut options = self.options;
options.set_encoding = true;
let mut encoder = Encoder::<RL, EL>::from_buffer(options, self.output, self.worker);
let cursor = ConstructedCursor::<RL, EL>::new(
C::FIELDS.number_of_optional_and_default_fields(),
C::IS_EXTENSIBLE,
);
encoder.cursor = cursor;
encoder_scope(&mut encoder)?;
if self.options.set_encoding {
encoder.encode_constructed::<RL, EL, C>(tag, Some(&mut self.set_output))?;
} else {
encoder.encode_constructed::<RL, EL, C>(tag, None)?;
}
encoder.collect_set();
Ok(())
}
fn encode_set_of<E: Encode + Eq + core::hash::Hash>(
&mut self,
tag: Tag,
value: &SetOf<E>,
constraints: Constraints,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.encode_sequence_of(tag, &value.to_vec(), constraints, Identifier::EMPTY)
}
fn encode_some<E: Encode>(
&mut self,
value: &E,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.set_presence(E::TAG, true);
value.encode(self)
}
fn encode_some_with_tag_and_constraints<E: Encode>(
&mut self,
tag: Tag,
constraints: Constraints,
value: &E,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
self.set_presence(tag, true);
value.encode_with_tag_and_constraints(self, tag, constraints, Identifier::EMPTY)
}
fn encode_none<E: Encode>(&mut self, _: Identifier) -> Result<Self::Ok, Self::Error> {
self.set_presence(E::TAG, false);
Ok(())
}
fn encode_none_with_tag(&mut self, tag: Tag, _: Identifier) -> Result<Self::Ok, Self::Error> {
self.set_presence(tag, false);
Ok(())
}
fn encode_choice<E: Encode + Choice>(
&mut self,
_: Constraints,
tag: Tag,
encode_fn: impl FnOnce(&mut Self) -> Result<Tag, Self::Error>,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
let mut tag_buffer: BitArray<[u8; core::mem::size_of::<Tag>() + 1], Msb0> =
BitArray::default();
let needed = self.encode_tag(tag, tag_buffer.as_mut_bitslice());
self.output
.extend_from_slice(&tag_buffer.as_raw_slice()[..(needed / 8)]);
let buffer_end = self.output.len();
let _tag = encode_fn(self)?;
debug_assert_eq!(_tag, tag);
let is_root_extension = crate::types::TagTree::tag_contains(&tag, E::VARIANTS);
if is_root_extension {
} else {
self.worker.append(&mut self.output.split_off(buffer_end));
Self::encode_length(self.output, self.worker.len())?;
self.output.append(self.worker);
}
self.extend(tag);
Ok(())
}
fn encode_extension_addition<E: Encode>(
&mut self,
tag: Tag,
constraints: Constraints,
value: E,
_: Identifier,
) -> Result<Self::Ok, Self::Error> {
if value.is_present() {
if self.cursor.extension_bitmap_cursor == 0 {
self.extension_bitmap_reserve();
}
let cursor = self.output.len();
let mut encoder = Encoder::<0>::from_buffer(self.options, self.worker, self.output);
E::encode_with_tag_and_constraints(
&value,
&mut encoder,
tag,
constraints,
Identifier::EMPTY,
)?;
encoder.worker.truncate(cursor);
Self::encode_length(encoder.worker, encoder.output.len())?;
self.output.append(self.worker);
self.set_extension_presence(true);
} else {
self.set_extension_presence(false);
}
Ok(())
}
fn encode_extension_addition_group<const RL: usize, const EL: usize, E>(
&mut self,
value: Option<&E>,
_: Identifier,
) -> Result<Self::Ok, Self::Error>
where
E: Encode + Constructed<RL, EL>,
{
let Some(value) = value else {
self.set_extension_presence(false);
return Ok(());
};
if self.cursor.extension_bitmap_cursor == 0 {
self.extension_bitmap_reserve();
}
self.is_extension_sequence = true;
let cursor = self.output.len();
let mut encoder = Encoder::<0>::from_buffer(self.options, self.worker, self.output);
value.encode(&mut encoder)?;
encoder.worker.truncate(cursor);
self.is_extension_sequence = false;
Self::encode_length(encoder.worker, encoder.output.len())?;
self.output.append(self.worker);
self.set_extension_presence(true);
Ok(())
}
}
#[cfg(test)]
mod tests {
use num_bigint::BigInt;
use super::*;
use crate::prelude::{AsnType, Decode, Encode};
#[test]
fn test_encode_bool() {
let output = crate::coer::encode(&true).unwrap();
let bv = BitVec::<u8, Msb0>::from_slice(&[0xffu8]);
assert_eq!(output, bv.as_raw_slice());
let output = crate::coer::encode(&false).unwrap();
let bv = BitVec::<u8, Msb0>::from_slice(&[0x00u8]);
assert_eq!(output, bv.as_raw_slice());
let decoded = crate::coer::encode(&true).unwrap();
assert_eq!(decoded, &[0xffu8]);
let decoded = crate::coer::encode(&false).unwrap();
assert_eq!(decoded, &[0x0]);
}
#[test]
fn test_encode_integer_manual_setup() {
const CONSTRAINT_1: Constraints = constraints!(value_constraint!(0, 255));
let mut buffer = vec![];
let mut wb = vec![];
let mut encoder =
Encoder::<0, 0>::from_buffer(EncoderOptions::coer(), &mut buffer, &mut wb);
let result = encoder.encode_integer_with_constraints(Tag::INTEGER, &CONSTRAINT_1, &244);
assert!(result.is_ok());
let v = vec![244u8];
assert_eq!(encoder.output.clone(), v);
encoder.output.clear();
let value = BigInt::from(256);
let result = encoder.encode_integer_with_constraints(Tag::INTEGER, &CONSTRAINT_1, &value);
assert!(result.is_err());
}
#[test]
fn test_integer_with_length_determinant() {
let constraints = Constraints::default();
let mut buffer = vec![];
let mut wb = vec![];
let mut encoder =
Encoder::<0, 0>::from_buffer(EncoderOptions::coer(), &mut buffer, &mut wb);
let result =
encoder.encode_integer_with_constraints(Tag::INTEGER, &constraints, &BigInt::from(244));
assert!(result.is_ok());
let v = vec![2u8, 0, 244];
assert_eq!(encoder.output.to_vec(), v);
encoder.output.clear();
let result = encoder.encode_integer_with_constraints(
Tag::INTEGER,
&constraints,
&BigInt::from(-1_234_567),
);
assert!(result.is_ok());
let v = vec![0x03u8, 0xED, 0x29, 0x79];
assert_eq!(encoder.output.to_vec(), v);
}
#[test]
fn test_large_lengths() {
let constraints = Constraints::default();
let mut buffer = vec![];
let mut wb = vec![];
let mut encoder =
Encoder::<0, 0>::from_buffer(EncoderOptions::coer(), &mut buffer, &mut wb);
let number: BigInt = BigInt::from(256).pow(127) - 1;
let result = encoder.encode_integer_with_constraints(Tag::INTEGER, &constraints, &number);
assert!(result.is_ok());
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,
];
assert_eq!(encoder.output(), vc);
}
#[test]
fn test_choice() {
use crate as rasn;
use crate::types::Integer;
#[derive(AsnType, Decode, Debug, Encode, PartialEq)]
#[rasn(choice, automatic_tags)]
#[non_exhaustive]
enum Choice {
Normal(Integer),
High(Integer),
#[rasn(extension_addition)]
Medium(Integer),
}
let mut buffer = vec![];
let mut wb = vec![];
let mut encoder =
Encoder::<0, 0>::from_buffer(EncoderOptions::coer(), &mut buffer, &mut wb);
let choice = Choice::Normal(333.into());
choice.encode(&mut encoder).unwrap();
assert_eq!(encoder.output(), &[128, 2, 1, 77]);
}
}