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> {
bytes: D,
tag: u8,
len: Len,
}
impl<'bytes> Any<&'bytes [u8]> {
#[inline]
pub const fn new(bytes: &'bytes [u8], tag: u8, len: Len) -> Self {
Self { bytes, tag, len }
}
}
impl<D> Any<D> {
#[inline]
pub const fn bytes(&self) -> &D {
&self.bytes
}
pub const fn len(&self) -> &Len {
&self.len
}
pub const fn tag(&self) -> u8 {
self.tag
}
}
impl<D> Any<D>
where
D: Lease<[u8]>,
{
#[inline]
pub fn data(&self) -> &[u8] {
let skip = 1u8.wrapping_add(self.len.bytes().len());
unsafe { self.bytes.lease().get(skip.into()..).unwrap_unchecked() }
}
}
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, _) = decode_asn1_tlv(dw.bytes)?;
let idx = 1usize.wrapping_add(len.bytes().len().into()).wrapping_add(data.len());
let Some((lhs, rhs)) = dw.bytes.split_at_checked(idx) else {
return Err(Asn1Error::InvalidAnyBytes.into());
};
dw.bytes = rhs;
Ok(Self { bytes: lhs, 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.bytes.lease()])?;
Ok(())
}
}