extern crate alloc;
use arbitrary_int::{traits::Integer, u10, u6};
use num_traits::ToBytes;
#[cfg(not(feature = "json"))]
use alloc::vec;
#[allow(clippy::wildcard_imports)]
use super::*;
#[derive(Debug)]
pub enum EncodeError {
Unsupported(alloc::string::String),
Common(alloc::string::String),
#[cfg(feature = "json")]
Json(alloc::string::String),
}
impl EncodeError {
#[must_use]
pub fn message(&self) -> &str {
match self {
Self::Unsupported(message) => message,
Self::Common(message) => message,
#[cfg(feature = "json")]
Self::Json(message) => message,
}
}
}
#[derive(Debug, Default)]
pub struct Encoder {
bytes: Vec<u8>,
}
impl Encoder {
#[must_use]
pub fn new() -> Self {
Self::default()
}
}
impl From<Encoder> for alloc::vec::Vec<u8> {
fn from(val: Encoder) -> Self {
val.bytes
}
}
pub trait Encode {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError>;
fn encode_to_vec(&self) -> Result<Vec<u8>, EncodeError> {
let mut encoder = Encoder::new();
self.encode(&mut encoder)?;
Ok(encoder.into())
}
#[cfg(feature = "json")]
fn encode_to_json(&self) -> Result<alloc::string::String, EncodeError>
where
Self: Sized + Serialize,
{
serde_json::to_string(self)
.map_err(|e| EncodeError::Json(alloc::format!("Error encoding JSON: {e:?}")))
}
}
trait BitwiseWrite {
fn write_bitwise(&self, bit_count: usize, output: &mut Vec<bool>);
}
macro_rules! write_int_bitwise {
($typ:ty, $max_bits:expr) => {
impl BitwiseWrite for $typ {
fn write_bitwise(&self, bit_count: usize, output: &mut Vec<bool>) {
for idx in (0..bit_count).rev() {
let bit = ((self >> idx) & 0x01) == 1;
output.push(bit)
}
}
}
};
}
write_int_bitwise!(u8, 8);
write_int_bitwise!(u16, 16);
write_int_bitwise!(i16, 16);
write_int_bitwise!(u32, 32);
write_int_bitwise!(i32, 32);
trait BitwiseEncode {
fn encode_bitwise(&self, output: &mut Vec<bool>);
}
impl BitwiseEncode for bool {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
output.push(*self);
}
}
macro_rules! encode_int {
($typ:ty) => {
impl Encode for $typ {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bytes = self.to_be_bytes();
output.bytes.extend_from_slice(&bytes);
Ok(())
}
}
};
}
encode_int!(u16);
encode_int!(i16);
encode_int!(u32);
encode_int!(i32);
impl Encode for u8 {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
output.bytes.push(*self);
Ok(())
}
}
impl BitwiseEncode for u10 {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
self.as_u16().write_bitwise(10, output);
}
}
impl BitwiseEncode for u4 {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
self.as_u8().write_bitwise(4, output);
}
}
impl BitwiseEncode for i15 {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
self.as_i16().write_bitwise(15, output);
}
}
impl BitwiseEncode for u6 {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
self.as_u8().write_bitwise(6, output);
}
}
impl<const SIZE: usize> Encode for [u8; SIZE] {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
output.bytes.extend_from_slice(self);
Ok(())
}
}
impl Encode for [bool; 8] {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let byte = (u8::from(self[0]) << 7)
+ (u8::from(self[1]) << 6)
+ (u8::from(self[2]) << 5)
+ (u8::from(self[3]) << 4)
+ (u8::from(self[4]) << 3)
+ (u8::from(self[5]) << 2)
+ (u8::from(self[6]) << 1)
+ (u8::from(self[7]));
output.bytes.push(byte);
Ok(())
}
}
impl Encode for Vec<bool> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
if self.len().is_multiple_of(8) {
for bits in self.chunks(8) {
let bits: [bool; 8] = bits
.try_into()
.expect("Array chunk suddenly returned different size");
bits.encode(output)?;
}
Ok(())
} else {
Err(EncodeError::Common(alloc::format!(
"Can't encode {} bits to bytes (only multiples of 8 allowed)",
self.len()
)))
}
}
}
impl Encode for &'_ [u8] {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
output.bytes.extend_from_slice(self);
Ok(())
}
}
impl Encode for en302636_4_1::Lifetime {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.0.encode(output)
}
}
impl Encode for en302636_4_1::Timestamp {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.0.encode(output)
}
}
impl BitwiseEncode for en302636_4_1::StationType {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
let val = *self as u8;
val.write_bitwise(5, output);
}
}
impl Encode for en302636_4_1::Address {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let mut bv = vec![];
self.manually_configured.encode_bitwise(&mut bv); self.station_type.encode_bitwise(&mut bv); self.reserved.encode_bitwise(&mut bv); bv.encode(output)?;
self.address.encode(output)
}
}
impl BitwiseEncode for en302636_4_1::NextAfterBasic {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
let val = *self as u8;
val.write_bitwise(4, output);
}
}
impl Encode for en302636_4_1::BasicHeader {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let mut bv = vec![];
self.version.encode_bitwise(&mut bv); self.next_header.encode_bitwise(&mut bv);
let bits: [bool; 8] = bv.try_into().expect("Bit vector suddenly not 8 bits");
bits.encode(output)?;
self.reserved.encode(output)?;
self.lifetime.encode(output)?;
self.remaining_hop_limit.encode(output)
}
}
impl Encode for en302636_4_1::LongPositionVector {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.gn_address.encode(output)?;
self.timestamp.encode(output)?;
self.latitude.encode(output)?;
self.longitude.encode(output)?;
let mut bv = vec![];
self.position_accuracy.encode_bitwise(&mut bv); self.speed.encode_bitwise(&mut bv); bv.encode(output)?;
self.heading.encode(output)
}
}
impl Encode for en302636_4_1::ShortPositionVector {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.gn_address.encode(output)?;
self.timestamp.encode(output)?;
self.latitude.encode(output)?;
self.longitude.encode(output)
}
}
impl Encode for en302636_4_1::TrafficClass {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let mut bv = vec![];
self.store_carry_forward.encode_bitwise(&mut bv); self.channel_offload.encode_bitwise(&mut bv); self.traffic_class_id.encode_bitwise(&mut bv);
let bits: [bool; 8] = bv.try_into().expect("Bit vector suddenly not 8 bits");
bits.encode(output)
}
}
impl BitwiseEncode for en302636_4_1::NextAfterCommon {
fn encode_bitwise(&self, output: &mut Vec<bool>) {
let val = *self as u8;
val.write_bitwise(4, output);
}
}
impl Encode for en302636_4_1::HeaderType {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let (ty, subty) = match self {
en302636_4_1::HeaderType::Any => (0u8, 0u8),
en302636_4_1::HeaderType::Beacon => (1, 0),
en302636_4_1::HeaderType::GeoUnicast => (2, 0),
en302636_4_1::HeaderType::GeoAnycast(en302636_4_1::AreaType::Circular) => (3, 0),
en302636_4_1::HeaderType::GeoAnycast(en302636_4_1::AreaType::Rectangular) => (3, 1),
en302636_4_1::HeaderType::GeoAnycast(_) => (3, 2),
en302636_4_1::HeaderType::GeoBroadcast(en302636_4_1::AreaType::Circular) => (4, 0),
en302636_4_1::HeaderType::GeoBroadcast(en302636_4_1::AreaType::Rectangular) => (4, 1),
en302636_4_1::HeaderType::GeoBroadcast(_) => (4, 2),
en302636_4_1::HeaderType::TopologicallyScopedBroadcast(
en302636_4_1::BroadcastType::SingleHop,
) => (5, 0),
en302636_4_1::HeaderType::TopologicallyScopedBroadcast(_) => (5, 1),
en302636_4_1::HeaderType::LocationService(
en302636_4_1::LocationServiceType::Request,
) => (6, 0),
en302636_4_1::HeaderType::LocationService(_) => (6, 1),
};
let mut bv = vec![];
ty.write_bitwise(4, &mut bv);
subty.write_bitwise(4, &mut bv);
let bits: [bool; 8] = bv.try_into().expect("Bit vector suddenly not 8 bits");
bits.encode(output)
}
}
impl Encode for en302636_4_1::CommonHeader {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
{
let mut bv = vec![];
self.next_header.encode_bitwise(&mut bv); self.reserved_1.encode_bitwise(&mut bv);
let bits: [bool; 8] = bv.try_into().expect("Bit vector suddenly not 8 bits");
bits.encode(output)?;
}
self.header_type_and_subtype.encode(output)?;
self.traffic_class.encode(output)?;
self.flags.encode(output)?;
self.payload_length.encode(output)?;
self.maximum_hop_limit.encode(output)?;
self.reserved_2.encode(output)
}
}
impl Encode for en302636_4_1::GeoAnycast {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.sequence_number.encode(output)?;
self.reserved_1.encode(output)?;
self.source_position_vector.encode(output)?;
self.geo_area_position_latitude.encode(output)?;
self.geo_area_position_longitude.encode(output)?;
self.distance_a.encode(output)?;
self.distance_b.encode(output)?;
self.angle.encode(output)?;
self.reserved_2.encode(output)
}
}
impl Encode for en302636_4_1::GeoUnicast {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.sequence_number.encode(output)?;
self.reserved.encode(output)?;
self.source_position_vector.encode(output)?;
self.destination_position_vector.encode(output)
}
}
impl Encode for en302636_4_1::TopologicallyScopedBroadcast {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.sequence_number.encode(output)?;
self.reserved.encode(output)?;
self.source_position_vector.encode(output)
}
}
impl Encode for en302636_4_1::SingleHopBroadcast {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.source_position_vector.encode(output)?;
self.media_dependent_data.encode(output)
}
}
impl Encode for en302636_4_1::Beacon {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.source_position_vector.encode(output)
}
}
impl Encode for en302636_4_1::LSRequest {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.sequence_number.encode(output)?;
self.reserved.encode(output)?;
self.source_position_vector.encode(output)?;
self.request_gn_address.encode(output)
}
}
impl Encode for en302636_4_1::LSReply {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.sequence_number.encode(output)?;
self.reserved.encode(output)?;
self.source_position_vector.encode(output)?;
self.destination_position_vector.encode(output)
}
}
impl Encode for Option<en302636_4_1::ExtendedHeader> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Some(en302636_4_1::ExtendedHeader::Beacon(b)) => b.encode(output),
Some(en302636_4_1::ExtendedHeader::GAC(gac)) => gac.encode(output),
Some(en302636_4_1::ExtendedHeader::GBC(gbc)) => gbc.encode(output),
Some(en302636_4_1::ExtendedHeader::GUC(guc)) => guc.encode(output),
Some(en302636_4_1::ExtendedHeader::LSReply(lsr)) => lsr.encode(output),
Some(en302636_4_1::ExtendedHeader::LSRequest(lsr)) => lsr.encode(output),
Some(en302636_4_1::ExtendedHeader::SHB(shb)) => shb.encode(output),
Some(en302636_4_1::ExtendedHeader::TSB(tsb)) => tsb.encode(output),
None => Ok(()),
}
}
}
impl Encode for Packet<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
if let Self::Unsecured {
basic,
common,
extended,
payload,
} = self
{
basic.encode(output)?;
common.encode(output)?;
extended.encode(output)?;
payload.encode(output)
} else {
Err(EncodeError::Unsupported(
"Encoding secured headers is currently unsupported!".into(),
))
}
}
}
#[allow(clippy::unnecessary_wraps, reason = "common interface")]
fn encode_oer_length(length: usize, output: &mut Encoder) -> Result<(), EncodeError> {
match length {
len if len < 128 => {
#[allow(clippy::cast_possible_truncation)]
let value = len as u8;
output.bytes.push(value);
Ok(())
}
len => {
let raw = len.to_be_bytes();
let mut length_bytes = raw.as_ref();
while length_bytes.len() > 1 && length_bytes[0] == 0 {
length_bytes = &length_bytes[1..];
}
#[allow(clippy::cast_possible_truncation)]
let len_byte = 0x80 | (length_bytes.len() as u8);
output.bytes.push(len_byte);
output.bytes.extend_from_slice(length_bytes);
Ok(())
}
}
}
fn encode_oer_integer<I: num::Integer + ToBytes>(
min: Option<i128>,
max: Option<i128>,
value: &I,
output: &mut Encoder,
) -> Result<(), EncodeError> {
match (min, max) {
(Some(_), Some(_)) => {
output.bytes.extend_from_slice(value.to_be_bytes().as_ref());
Ok(())
}
(Some(min), _) if min >= 0 => {
let raw = value.to_be_bytes();
let mut bytes = raw.as_ref();
while bytes.len() > 1 && bytes[0] == 0 {
bytes = &bytes[1..];
}
encode_oer_length(bytes.len(), output)?;
output.bytes.extend_from_slice(bytes);
Ok(())
}
_ => Err(EncodeError::Unsupported(
"Unconstrained or extensible integers are unsupported!".into(),
)),
}
}
fn encode_oer_enumerated(value: u8, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_integer(Some(0), Some(255), &value, output)
}
fn encode_oer_octetstring(
min: Option<usize>,
max: Option<usize>,
value: &[u8],
output: &mut Encoder,
) -> Result<(), EncodeError> {
match (min, max) {
(Some(min), Some(max)) if min == max => {
output.bytes.extend_from_slice(value);
Ok(())
}
_ => {
encode_oer_length(value.len(), output)?;
output.bytes.extend_from_slice(value);
Ok(())
}
}
}
#[allow(clippy::unnecessary_wraps, reason = "common interface")]
fn encode_oer_fixed_bitstring(value: &[bool], output: &mut Encoder) -> Result<(), EncodeError> {
let mut bv = value.to_vec();
bv.extend_from_slice(&vec![false; util::bitstring_padding_bits(bv.len())]); bv.encode(output)?;
Ok(())
}
fn encode_oer_varlength_bitstring(value: &[bool], output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_length(util::bitstring_buffer_size(value.len()) + 1, output)?;
let unused_bits = util::bitstring_padding_bits(value.len());
#[allow(clippy::cast_possible_truncation)]
encode_oer_integer(Some(0), Some(8), &(unused_bits as u8), output)?;
let mut bv = value.to_vec();
bv.extend_from_slice(&vec![false; util::bitstring_padding_bits(bv.len())]); bv.encode(output)?;
Ok(())
}
#[allow(clippy::unnecessary_wraps, reason = "common interface")]
fn encode_extension_and_optional_bitmap(
extension: Option<bool>,
bitmap: &[bool],
output: &mut Encoder,
) -> Result<(), EncodeError> {
let mut bv = vec![];
if let Some(is_extended) = extension {
bv.push(is_extended);
}
bv.extend_from_slice(bitmap);
bv.extend_from_slice(&vec![false; util::bitstring_padding_bits(bv.len())]); bv.encode(output)?;
Ok(())
}
fn encode_oer_tag(tag: u8, output: &mut Encoder) -> Result<(), EncodeError> {
match tag {
t if t < 63 => encode_oer_integer(Some(0), Some(255), &(t + 128), output),
_ => Err(EncodeError::Unsupported(
"Tag larger than 62 are unsupported!".into(),
)),
}
}
fn encode_oer_open_type<T: Encode>(value: &T, output: &mut Encoder) -> Result<(), EncodeError> {
let bytes = value.encode_to_vec()?;
encode_oer_octetstring(Some(0), None, &bytes, output)
}
impl<const SIZE: usize> Encode for ieee1609dot2::BitString<SIZE> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_fixed_bitstring(&self.0, output)
}
}
macro_rules! encode_int {
($typ:ty, $min:expr, $max:expr) => {
impl Encode for $typ {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_integer($min, $max, &self.0, output)
}
}
};
}
encode_int!(
ieee1609dot2::Latitude,
Some(-900_000_000),
Some(900_000_001)
);
encode_int!(
ieee1609dot2::Longitude,
Some(-1_799_999_999),
Some(1_800_000_001)
);
encode_int!(ieee1609dot2::PduFunctionalType, Some(0), Some(255));
encode_int!(ieee1609dot2::HeaderInfoContributorId, Some(0), Some(255));
encode_int!(ieee1609dot2::Uint8, Some(0), Some(255));
encode_int!(ieee1609dot2::Uint16, Some(0), Some(65535));
encode_int!(ieee1609dot2::Uint32, Some(0), Some(4_294_967_295));
encode_int!(ieee1609dot2::ExtId, Some(0), Some(255));
encode_int!(ieee1609dot2::Psid, Some(0), None);
impl Encode for ieee1609dot2::CertificateBase<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bitmap = [self.signature.is_some()];
encode_extension_and_optional_bitmap(None, &bitmap, output)?;
self.version.encode(output)?;
self.r_type.encode(output)?;
self.issuer.encode(output)?;
self.to_be_signed.encode(output)?;
if let Some(sig) = &self.signature {
sig.encode(output)?;
}
Ok(())
}
}
macro_rules! encode_octets {
($typ:ty, $min:expr, $max:expr) => {
impl Encode for $typ {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring($min, $max, self.0, output)
}
}
};
}
encode_octets!(ieee1609dot2::LinkageValue<'_>, Some(9), Some(9));
encode_octets!(ieee1609dot2::HashedId3<'_>, Some(3), Some(3));
encode_octets!(ieee1609dot2::HashedId8<'_>, Some(8), Some(8));
encode_octets!(ieee1609dot2::SubjectAssurance<'_>, Some(1), Some(1));
encode_octets!(ieee1609dot2::BitmapSsp<'_>, Some(0), Some(31));
encode_octets!(ieee1609dot2::Opaque<'_>, Some(0), None);
encode_octets!(ieee1609dot2::HashedId32<'_>, Some(32), Some(32));
encode_octets!(ieee1609dot2::HashedId48<'_>, Some(48), Some(48));
impl Encode for ieee1609dot2::CertificateType {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_enumerated(*self as u8, output)
}
}
impl Encode for ieee1609dot2::HashAlgorithm {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_enumerated(*self as u8, output)
}
}
impl Encode for ieee1609dot2::IssuerIdentifier<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Sha256AndDigest(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::RsSelf(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::Sha384AndDigest(inner) => {
encode_oer_tag(2, output)?;
encode_oer_open_type(inner, output)
}
Self::Sm3AndDigest(inner) => {
encode_oer_tag(3, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::ToBeSignedCertificate<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let is_extended = self.flags.is_some()
|| self.app_extensions.is_some()
|| self.cert_issue_extensions.is_some()
|| self.cert_request_extension.is_some();
let bitmap = [
self.region.is_some(),
self.assurance_level.is_some(),
self.app_permissions.is_some(),
self.cert_issue_permissions.is_some(),
self.cert_request_permissions.is_some(),
self.can_request_rollover.is_some(),
self.encryption_key.is_some(),
];
encode_extension_and_optional_bitmap(Some(is_extended), &bitmap, output)?;
self.id.encode(output)?;
self.craca_id.encode(output)?;
self.crl_series.encode(output)?;
self.validity_period.encode(output)?;
self.region
.as_ref()
.map_or(Ok(()), |reg| reg.encode(output))?;
self.assurance_level
.as_ref()
.map_or(Ok(()), |sub_ass| sub_ass.encode(output))?;
self.app_permissions
.as_ref()
.map_or(Ok(()), |app_perm| app_perm.encode(output))?;
self.cert_issue_permissions
.as_ref()
.map_or(Ok(()), |cert_issue_perm| cert_issue_perm.encode(output))?;
self.cert_request_permissions
.as_ref()
.map_or(Ok(()), |cert_request_perm| cert_request_perm.encode(output))?;
self.encryption_key
.as_ref()
.map_or(Ok(()), |enc_key| enc_key.encode(output))?;
self.verify_key_indicator.encode(output)?;
let ext_bitmap = [
self.flags.is_some(),
self.app_extensions.is_some(),
self.cert_issue_extensions.is_some(),
self.cert_request_extension.is_some(),
];
if is_extended {
encode_oer_varlength_bitstring(&ext_bitmap, output)
} else {
Ok(())
}?;
self.flags
.as_ref()
.map_or(Ok(()), |flags| encode_oer_open_type(flags, output))?;
self.app_extensions
.as_ref()
.map_or(Ok(()), |app_ext| encode_oer_open_type(app_ext, output))?;
self.cert_issue_extensions
.as_ref()
.map_or(Ok(()), |cert_ext| encode_oer_open_type(cert_ext, output))?;
self.cert_request_extension
.as_ref()
.map_or(Ok(()), |cert_ext| encode_oer_open_type(cert_ext, output))?;
Ok(())
}
}
impl Encode for ieee1609dot2::AppExtension<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.id.encode(output)?;
encode_oer_octetstring(Some(0), None, self.content, output)
}
}
impl Encode for ieee1609dot2::CertIssueExtensionPermissions<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Specific(inner) => {
encode_oer_tag(0, output)?;
encode_oer_octetstring(Some(0), None, inner, output)
}
Self::All(()) => encode_oer_tag(1, output),
}
}
}
impl Encode for ieee1609dot2::CertRequestExtensionPermissions<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Content(inner) => {
encode_oer_tag(0, output)?;
encode_oer_octetstring(Some(0), None, inner, output)
}
Self::All(()) => encode_oer_tag(1, output),
}
}
}
impl Encode for ieee1609dot2::CertIssueExtension<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.id.encode(output)?;
self.permissions.encode(output)
}
}
impl Encode for ieee1609dot2::CertRequestExtension<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.id.encode(output)?;
self.permissions.encode(output)
}
}
impl Encode for ieee1609dot2::VerificationKeyIndicator<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::VerificationKey(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::ReconstructionValue(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
}
}
}
impl Encode for ieee1609dot2::PublicVerificationKey<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::EcdsaNistP256(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::EcdsaBrainpoolP256r1(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::EcdsaBrainpoolP384r1(inner) => {
encode_oer_tag(2, output)?;
encode_oer_open_type(inner, output)
}
Self::EcdsaNistP384(inner) => {
encode_oer_tag(3, output)?;
encode_oer_open_type(inner, output)
}
Self::EcsigSm2(inner) => {
encode_oer_tag(4, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::PsidGroupPermissions<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bitmap = [
self.min_chain_length == 1,
self.chain_length_range == 0,
self.ee_type
== ieee1609dot2::EndEntityType::from([
true, false, false, false, false, false, false, false,
]),
];
encode_extension_and_optional_bitmap(None, &bitmap, output)?;
self.subject_permissions.encode(output)?;
if bitmap[0] {
encode_oer_integer(Some(0), None, &self.min_chain_length, output)
} else {
Ok(())
}?;
if bitmap[1] {
encode_oer_integer(Some(0), None, &self.chain_length_range, output)
} else {
Ok(())
}?;
if bitmap[0] {
self.ee_type.encode(output)
} else {
Ok(())
}?;
Ok(())
}
}
impl Encode for ieee1609dot2::EndEntityType {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.0.encode(output)
}
}
impl Encode for ieee1609dot2::PsidSsp<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bitmap = [self.ssp.is_some()];
encode_extension_and_optional_bitmap(None, &bitmap, output)?;
self.psid.encode(output)?;
self.ssp.as_ref().map_or(Ok(()), |ssp| ssp.encode(output))
}
}
impl Encode for ieee1609dot2::PsidSspRange<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bitmap = [self.ssp_range.is_some()];
encode_extension_and_optional_bitmap(None, &bitmap, output)?;
self.psid.encode(output)?;
self.ssp_range
.as_ref()
.map_or(Ok(()), |ssp| ssp.encode(output))
}
}
impl Encode for ieee1609dot2::BitmapSspRange<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(1), Some(32), self.ssp_value, output)?;
encode_oer_octetstring(Some(1), Some(32), self.ssp_bitmask, output)
}
}
impl Encode for ieee1609dot2::SspRange<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Opaque(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::All(()) => encode_oer_tag(1, output),
Self::BitmapSspRange(inner) => {
encode_oer_tag(2, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::SubjectPermissions<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Explicit(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::All(()) => encode_oer_tag(1, output),
}
}
}
impl Encode for ieee1609dot2::ServiceSpecificPermissions<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Opaque(inner) => {
encode_oer_tag(0, output)?;
encode_oer_octetstring(Some(0), None, inner, output)
}
Self::BitmapSsp(inner) => {
encode_oer_tag(1, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::BasePublicEncryptionKey<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::EciesNistP256(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::EciesBrainpoolP256r1(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::EcencSm2(inner) => {
encode_oer_tag(2, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::EccP256CurvePoint<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::XOnly(inner) => {
encode_oer_tag(0, output)?;
encode_oer_octetstring(Some(32), Some(32), inner, output)
}
Self::Fill(()) => encode_oer_tag(1, output),
Self::CompressedY0(inner) => {
encode_oer_tag(2, output)?;
encode_oer_octetstring(Some(32), Some(32), inner, output)
}
Self::CompressedY1(inner) => {
encode_oer_tag(3, output)?;
encode_oer_octetstring(Some(32), Some(32), inner, output)
}
Self::UncompressedP256(inner) => {
encode_oer_tag(4, output)?;
inner.encode(output)
}
}
}
}
impl Encode for ieee1609dot2::EccP384CurvePoint<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::XOnly(inner) => {
encode_oer_tag(0, output)?;
encode_oer_octetstring(Some(48), Some(48), inner, output)
}
Self::Fill(()) => encode_oer_tag(1, output),
Self::CompressedY0(inner) => {
encode_oer_tag(2, output)?;
encode_oer_octetstring(Some(48), Some(48), inner, output)
}
Self::CompressedY1(inner) => {
encode_oer_tag(3, output)?;
encode_oer_octetstring(Some(48), Some(48), inner, output)
}
Self::UncompressedP384(inner) => {
encode_oer_tag(4, output)?;
inner.encode(output)
}
}
}
}
macro_rules! encode_sequence_of {
($typ:ty) => {
impl Encode for $typ {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_integer(Some(0), None, &self.0.len(), output)?;
for inner in &self.0 {
inner.encode(output)?;
}
Ok(())
}
}
};
}
encode_sequence_of!(ieee1609dot2::SequenceOfUint16);
encode_sequence_of!(ieee1609dot2::SequenceOfUint8);
encode_sequence_of!(ieee1609dot2::SequenceOfRegionAndSubregions);
encode_sequence_of!(ieee1609dot2::SequenceOfRectangularRegion);
encode_sequence_of!(ieee1609dot2::SequenceOfIdentifiedRegion);
encode_sequence_of!(ieee1609dot2::PolygonalRegion);
encode_sequence_of!(ieee1609dot2::SequenceOfPsidSspRange<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfPsid);
encode_sequence_of!(ieee1609dot2::SequenceOfPsidSsp<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfOctetString<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfPsidGroupPermissions<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfAppExtensions<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfCertIssueExtensions<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfCertRequestExtensions<'_>);
encode_sequence_of!(ieee1609dot2::SequenceOfHashedId3<'_>);
encode_sequence_of!(ieee1609dot2::ContributedExtensionBlocks<'_>);
encode_sequence_of!(ieee1609dot2::ContributedExtensionBlockExtns<'_>);
macro_rules! encode_sequence {
($typ:ty, $( $field:ident ),*) => {
impl Encode for $typ {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
$(
self.$field.encode(output)?;
)*
Ok(())
}
}
};
}
encode_sequence!(ieee1609dot2::ValidityPeriod, start, duration);
encode_sequence!(ieee1609dot2::CountryAndRegions, country_only, regions);
encode_sequence!(ieee1609dot2::RegionAndSubregions, region, subregions);
encode_sequence!(
ieee1609dot2::CountryAndSubregions,
country_only,
region_and_subregions
);
encode_sequence!(ieee1609dot2::ThreeDLocation, latitude, longitude, elevation);
encode_sequence!(ieee1609dot2::TwoDLocation, latitude, longitude);
encode_sequence!(ieee1609dot2::RectangularRegion, north_west, south_east);
encode_sequence!(ieee1609dot2::CircularRegion, center, radius);
encode_sequence!(
ieee1609dot2::PublicEncryptionKey<'_>,
supported_symm_alg,
public_key
);
encode_sequence!(ieee1609dot2::ToBeSignedData<'_>, payload, header_info);
encode_sequence!(
ieee1609dot2::Ieee1609Dot2Data<'_>,
protocol_version,
content
);
encode_sequence!(
ieee1609dot2::ContributedExtensionBlock<'_>,
contributor_id,
extns
);
impl Encode for ieee1609dot2::SymmAlgorithm {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_enumerated(*self as u8, output)
}
}
impl Encode for ieee1609dot2::GeographicRegion {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::CircularRegion(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::RectangularRegion(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::PolygonalRegion(inner) => {
encode_oer_tag(2, output)?;
inner.encode(output)
}
Self::IdentifiedRegion(inner) => {
encode_oer_tag(3, output)?;
inner.encode(output)
}
}
}
}
impl Encode for ieee1609dot2::IdentifiedRegion {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::CountryOnly(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::CountryAndRegions(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::CountryAndSubregions(inner) => {
encode_oer_tag(2, output)?;
inner.encode(output)
}
}
}
}
impl Encode for ieee1609dot2::Duration {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Microseconds(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::Milliseconds(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::Seconds(inner) => {
encode_oer_tag(2, output)?;
inner.encode(output)
}
Self::Minutes(inner) => {
encode_oer_tag(3, output)?;
inner.encode(output)
}
Self::Hours(inner) => {
encode_oer_tag(4, output)?;
inner.encode(output)
}
Self::SixtyHours(inner) => {
encode_oer_tag(5, output)?;
inner.encode(output)
}
Self::Years(inner) => {
encode_oer_tag(6, output)?;
inner.encode(output)
}
}
}
}
impl Encode for ieee1609dot2::CertificateId<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::LinkageData(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::Name(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::BinaryId(inner) => {
encode_oer_tag(2, output)?;
encode_oer_octetstring(Some(1), Some(64), inner, output)
}
Self::None(()) => encode_oer_tag(3, output),
}
}
}
impl Encode for ieee1609dot2::Hostname {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(0), Some(255), self.0.as_bytes(), output)
}
}
impl Encode for ieee1609dot2::LinkageData<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bitmap = [self.group_linkage_value.is_some()];
encode_extension_and_optional_bitmap(None, &bitmap, output)?;
self.i_cert.encode(output)?;
self.linkage_value.encode(output)?;
self.group_linkage_value
.as_ref()
.map_or(Ok(()), |glv| glv.encode(output))
}
}
impl Encode for ieee1609dot2::GroupLinkageValue<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(4), Some(4), self.j_value, output)?;
encode_oer_octetstring(Some(9), Some(9), self.value, output)
}
}
impl Encode for ieee1609dot2::EccP256CurvePointUncompressedP256<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(32), Some(32), self.x, output)?;
encode_oer_octetstring(Some(32), Some(32), self.y, output)
}
}
impl Encode for ieee1609dot2::EccP384CurvePointUncompressedP384<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(48), Some(48), self.x, output)?;
encode_oer_octetstring(Some(48), Some(48), self.y, output)
}
}
impl Encode for ieee1609dot2::EcsigP256Signature<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(32), Some(32), self.r_sig, output)?;
encode_oer_octetstring(Some(32), Some(32), self.s_sig, output)
}
}
impl Encode for ieee1609dot2::EcdsaP256Signature<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.r_sig.encode(output)?;
encode_oer_octetstring(Some(32), Some(32), self.s_sig, output)
}
}
impl Encode for ieee1609dot2::EcdsaP384Signature<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
self.r_sig.encode(output)?;
encode_oer_octetstring(Some(48), Some(48), self.s_sig, output)
}
}
impl Encode for ieee1609dot2::Signature<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::EcdsaNistP256Signature(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::EcdsaBrainpoolP256r1Signature(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
Self::EcdsaBrainpoolP384r1Signature(inner) => {
encode_oer_tag(2, output)?;
encode_oer_open_type(inner, output)
}
Self::EcdsaNistP384Signature(inner) => {
encode_oer_tag(3, output)?;
encode_oer_open_type(inner, output)
}
Self::Sm2Signature(inner) => {
encode_oer_tag(4, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::HashedData<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Sha256HashedData(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::Sha384HashedData(inner) => {
encode_oer_tag(1, output)?;
encode_oer_open_type(inner, output)
}
Self::Sm3HashedData(inner) => {
encode_oer_tag(2, output)?;
encode_oer_open_type(inner, output)
}
}
}
}
impl Encode for ieee1609dot2::EncryptionKey<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Public(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
Self::Symmetric(inner) => {
encode_oer_tag(1, output)?;
inner.encode(output)
}
}
}
}
impl Encode for ieee1609dot2::SymmetricEncryptionKey<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
Self::Aes128Ccm(inner) => {
encode_oer_tag(0, output)?;
encode_oer_octetstring(Some(16), Some(16), inner, output)
}
Self::Sm4Ccm(inner) => {
encode_oer_tag(1, output)?;
let mut encoder = Encoder::new();
encode_oer_octetstring(Some(16), Some(16), inner, &mut encoder)?;
#[cfg(not(feature = "validate"))]
let inner_encoded: Vec<u8> = encoder.into();
#[cfg(feature = "validate")]
let inner_encoded: alloc::vec::Vec<u8> = encoder.into();
encode_oer_octetstring(Some(0), None, inner_encoded.as_slice(), output)
}
}
}
}
impl Encode for ieee1609dot2::AnonymousContributedExtensionBlockExtns<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_oer_octetstring(Some(0), None, self.0, output)
}
}
impl Encode for ieee1609dot2::SignedDataPayload<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let bitmap = [self.data.is_some(), self.ext_data_hash.is_some()];
encode_extension_and_optional_bitmap(Some(self.omitted.is_some()), &bitmap, output)?;
self.data
.as_ref()
.map_or(Ok(()), |data| data.encode(output))?;
self.ext_data_hash
.as_ref()
.map_or(Ok(()), |hash| hash.encode(output))?;
self.omitted
.map_or(Ok(()), |()| encode_oer_varlength_bitstring(&[true], output))
}
}
impl Encode for ieee1609dot2::Ieee1609Dot2Content<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
match self {
ieee1609dot2::Ieee1609Dot2Content::UnsecuredData(inner) => {
encode_oer_tag(0, output)?;
inner.encode(output)
}
_ => todo!(),
}
}
}
encode_int!(
ieee1609dot2::Uint64,
Some(0),
Some(18_446_744_073_709_551_615)
);
impl Encode for ieee1609dot2::HeaderInfo<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
let is_extended = self.inline_p2pcd_request.is_some()
|| self.requested_certificate.is_some()
|| self.pdu_functional_type.is_some()
|| self.contributed_extensions.is_some();
let bitmap = [
self.generation_time.is_some(),
self.expiry_time.is_some(),
self.generation_location.is_some(),
self.p2pcd_learning_request.is_some(),
self.missing_crl_identifier.is_some(),
self.encryption_key.is_some(),
];
encode_extension_and_optional_bitmap(Some(is_extended), &bitmap, output)?;
self.psid.encode(output)?;
self.generation_time
.as_ref()
.map_or(Ok(()), |time| time.encode(output))?;
self.expiry_time
.as_ref()
.map_or(Ok(()), |time| time.encode(output))?;
self.generation_location
.as_ref()
.map_or(Ok(()), |location| location.encode(output))?;
self.p2pcd_learning_request
.as_ref()
.map_or(Ok(()), |id| id.encode(output))?;
self.missing_crl_identifier
.as_ref()
.map_or(Ok(()), |id| id.encode(output))?;
self.encryption_key
.as_ref()
.map_or(Ok(()), |enc_key| enc_key.encode(output))?;
let ext_bitmap = [
self.inline_p2pcd_request.is_some(),
self.requested_certificate.is_some(),
self.pdu_functional_type.is_some(),
self.contributed_extensions.is_some(),
];
if is_extended {
encode_oer_varlength_bitstring(&ext_bitmap, output)
} else {
Ok(())
}?;
self.inline_p2pcd_request
.as_ref()
.map_or(Ok(()), |request| encode_oer_open_type(request, output))?;
self.requested_certificate
.as_ref()
.map_or(Ok(()), |cert| encode_oer_open_type(cert, output))?;
self.pdu_functional_type
.as_ref()
.map_or(Ok(()), |ty| encode_oer_open_type(ty, output))?;
self.contributed_extensions
.as_ref()
.map_or(Ok(()), |ext| encode_oer_open_type(ext, output))?;
Ok(())
}
}
impl Encode for ieee1609dot2::MissingCrlIdentifier<'_> {
fn encode(&self, output: &mut Encoder) -> Result<(), EncodeError> {
encode_extension_and_optional_bitmap(Some(false), &[], output)?;
self.craca_id.encode(output)?;
self.crl_series.encode(output)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn encodes_oer_integer() {
let mut encoder = Encoder::new();
encode_oer_integer(Some(0), Some(255), &3u8, &mut encoder).unwrap();
assert_eq!(
&[3],
<encode::Encoder as std::convert::Into<Vec<u8>>>::into(encoder).as_slice()
);
let mut encoder = Encoder::new();
ieee1609dot2::Uint8(3).encode(&mut encoder).unwrap();
assert_eq!(
&[3],
<encode::Encoder as std::convert::Into<Vec<u8>>>::into(encoder).as_slice()
);
let mut encoder = Encoder::new();
encode_oer_integer(Some(-900_000_000), Some(900_000_001), &32i32, &mut encoder).unwrap();
assert_eq!(
&[0, 0, 0, 32],
<encode::Encoder as std::convert::Into<Vec<u8>>>::into(encoder).as_slice()
);
let mut encoder = Encoder::new();
ieee1609dot2::NinetyDegreeInt(32)
.encode(&mut encoder)
.unwrap();
assert_eq!(
&[0, 0, 0, 32],
<encode::Encoder as std::convert::Into<Vec<u8>>>::into(encoder).as_slice()
);
}
#[test]
fn encodes_oer_bitstring() {
let mut encoder = Encoder::new();
encode_oer_fixed_bitstring(&[true], &mut encoder).unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[0x80], output.as_slice());
let mut encoder = Encoder::new();
encode_oer_fixed_bitstring(
&[true, false, false, false, false, false, false, false],
&mut encoder,
)
.unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[0x80], output.as_slice());
let mut encoder = Encoder::new();
encode_oer_fixed_bitstring(
&[
true, false, false, false, false, false, false, false, false, true,
],
&mut encoder,
)
.unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[0x80, 0x40], output.as_slice());
let mut encoder = Encoder::new();
encode_oer_varlength_bitstring(&[true, false], &mut encoder).unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[2, 6, 0x80], output.as_slice());
let mut encoder = Encoder::new();
encode_oer_varlength_bitstring(
&[true, false, false, false, false, false, false, false],
&mut encoder,
)
.unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[2, 0, 0x80], output.as_slice());
let mut encoder = Encoder::new();
encode_oer_varlength_bitstring(
&[
true, false, false, false, false, false, false, false, false, true,
],
&mut encoder,
)
.unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[3, 6, 0x80, 0x40], output.as_slice());
let mut encoder = Encoder::new();
encode_oer_varlength_bitstring(
&[
true, false, false, false, false, false, false, false, false, true, false, false,
false, false, true, false,
],
&mut encoder,
)
.unwrap();
let output: Vec<u8> = encoder.into();
assert_eq!(&[3, 0, 0x80, 0x42], output.as_slice());
}
}