use crate::{
asn1::{Asn1DecodeWrapper, Asn1EncodeWrapper, Asn1Error, Len, decode_asn1_tlv},
codec::{Decode, DecodeWrapper, Encode, EncodeWrapper, GenericCodec},
misc::Lease,
};
#[derive(Clone, Debug, PartialEq)]
pub struct Any<D> {
tag: u8,
len: Len,
data: D,
}
impl<'any> Any<&'any [u8]> {
#[inline]
pub fn from_bytes(tag: u8, data: &'any [u8]) -> crate::Result<Self> {
Ok(Self::from_bytes_opt(tag, data).ok_or(Asn1Error::InvalidAnyBytes)?)
}
#[inline]
pub const fn from_bytes_opt(tag: u8, data: &'any [u8]) -> Option<Self> {
let data_len = data.len();
if data_len > 255 {
return None;
}
Some(Self { tag, len: Len::from_u8(data_len as u8), data })
}
}
impl<D> Any<D> {
#[inline]
pub const fn data(&self) -> &D {
&self.data
}
pub const fn len(&self) -> &Len {
&self.len
}
pub const fn tag(&self) -> u8 {
self.tag
}
}
impl<'de> Decode<'de, GenericCodec<Asn1DecodeWrapper, ()>> for Any<&'de [u8]> {
#[inline]
fn decode(dw: &mut DecodeWrapper<'de, Asn1DecodeWrapper>) -> crate::Result<Self> {
let (tag, len, data, rest) = decode_asn1_tlv(dw.bytes)?;
dw.bytes = rest;
Ok(Self { data, len, tag })
}
}
impl<D> Encode<GenericCodec<(), Asn1EncodeWrapper>> for Any<D>
where
D: Lease<[u8]>,
{
#[inline]
fn encode(&self, ew: &mut EncodeWrapper<'_, Asn1EncodeWrapper>) -> crate::Result<()> {
let _ =
ew.buffer.extend_from_copyable_slices([&[self.tag][..], &*self.len, self.data.lease()])?;
Ok(())
}
}