use crate::{
asn1::{Asn1DecodeWrapper, Asn1EncodeWrapper, Len, SequenceBuffer},
codec::{Decode, DecodeWrapper, Encode, EncodeWrapper, GenericCodec},
collection::TryExtend,
misc::{Lease, SingleTypeStorage},
};
#[derive(Debug, Default, PartialEq)]
pub struct Opt<T>(
pub T,
);
impl<'de, T> Opt<Option<T>>
where
T: Decode<'de, GenericCodec<Asn1DecodeWrapper, ()>>,
{
pub fn decode(dw: &mut DecodeWrapper<'de, Asn1DecodeWrapper>, tag: u8) -> crate::Result<Self> {
if dw.bytes.first().copied() == Some(tag) {
dw.decode_aux.tag = Some(tag);
let rslt = T::decode(dw);
dw.decode_aux.tag = None;
Ok(Self(Some(rslt?)))
} else {
Ok(Self(None))
}
}
}
impl<'de, B, E> Opt<Option<B>>
where
B: Default + SingleTypeStorage<Item = E> + TryExtend<[E; 1]>,
E: Decode<'de, GenericCodec<Asn1DecodeWrapper, ()>>,
{
pub fn decode_seq(
dw: &mut DecodeWrapper<'de, Asn1DecodeWrapper>,
tag: u8,
) -> crate::Result<Self> {
if dw.bytes.first().copied() == Some(tag) {
Ok(Self(Some(SequenceBuffer::<B>::decode(dw, tag)?.0)))
} else {
Ok(Self(None))
}
}
}
impl<E, T> Opt<T>
where
T: Lease<Option<E>> + SingleTypeStorage<Item = E>,
E: Encode<GenericCodec<(), Asn1EncodeWrapper>>,
{
pub fn encode(
&self,
ew: &mut EncodeWrapper<'_, Asn1EncodeWrapper>,
tag: u8,
) -> crate::Result<()> {
if let Some(elem) = self.0.lease() {
ew.encode_aux.tag = Some(tag);
let rslt = elem.encode(ew);
ew.encode_aux.tag = None;
rslt?;
}
Ok(())
}
}
impl<B, E, T> Opt<T>
where
T: Lease<Option<B>> + SingleTypeStorage<Item = B>,
B: Lease<[E]> + SingleTypeStorage<Item = E>,
E: Encode<GenericCodec<(), Asn1EncodeWrapper>>,
{
pub fn encode_seq(
&self,
ew: &mut EncodeWrapper<'_, Asn1EncodeWrapper>,
len_guess: Len,
tag: u8,
) -> crate::Result<()> {
if let Some(elem) = self.0.lease() {
SequenceBuffer(elem).encode(ew, len_guess, tag)?;
}
Ok(())
}
}