use crate::*;
use core::convert::TryFrom;
use core::marker::PhantomData;
impl<'a, T, E, const CLASS: u8, const TAG: u32> TryFrom<Any<'a>>
for TaggedValue<T, E, Implicit, CLASS, TAG>
where
T: TryFrom<Any<'a>, Error = E>,
T: Tagged,
E: From<Error>,
{
type Error = E;
fn try_from(any: Any<'a>) -> Result<Self, E> {
TryFrom::try_from(&any)
}
}
impl<'a, 'b, E, T, const CLASS: u8, const TAG: u32> TryFrom<&'b Any<'a>>
for TaggedValue<T, E, Implicit, CLASS, TAG>
where
T: TryFrom<Any<'a>, Error = E>,
T: Tagged,
E: From<Error>,
{
type Error = E;
fn try_from(any: &'b Any<'a>) -> Result<Self, E> {
any.tag().assert_eq(Tag(TAG))?;
if any.class() as u8 != CLASS {
let class = Class::try_from(CLASS).ok();
return Err(Error::unexpected_class(class, any.class()).into());
}
let any = Any {
header: Header {
tag: T::TAG,
..any.header.clone()
},
data: any.data,
};
match T::try_from(any) {
Ok(inner) => Ok(TaggedValue::implicit(inner)),
Err(e) => Err(e),
}
}
}
impl<'a, T, E, const CLASS: u8, const TAG: u32> FromDer<'a, E>
for TaggedValue<T, E, Implicit, CLASS, TAG>
where
T: TryFrom<Any<'a>, Error = E>,
T: Tagged,
E: From<Error>,
{
fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E> {
let (rem, any) = Any::from_der(bytes).map_err(Err::convert)?;
any.tag()
.assert_eq(Tag(TAG))
.map_err(|e| Err::Error(e.into()))?;
if any.class() as u8 != CLASS {
let class = Class::try_from(CLASS).ok();
return Err(Err::Error(
Error::unexpected_class(class, any.class()).into(),
));
}
let any = Any {
header: Header {
tag: T::TAG,
..any.header.clone()
},
data: any.data,
};
match T::try_from(any) {
Ok(inner) => Ok((rem, TaggedValue::implicit(inner))),
Err(e) => Err(nom::Err::Error(e)),
}
}
}
impl<T, E, const CLASS: u8, const TAG: u32> CheckDerConstraints
for TaggedValue<T, E, Implicit, CLASS, TAG>
where
T: CheckDerConstraints,
T: Tagged,
{
fn check_constraints(any: &Any) -> Result<()> {
any.header.length.assert_definite()?;
let header = any.header.clone().with_tag(T::TAG);
let inner = Any::new(header, any.data);
T::check_constraints(&inner)?;
Ok(())
}
}
#[cfg(feature = "std")]
impl<T, E, const CLASS: u8, const TAG: u32> ToDer for TaggedValue<T, E, Implicit, CLASS, TAG>
where
T: ToDer,
{
fn to_der_len(&self) -> Result<usize> {
self.inner.to_der_len()
}
fn write_der(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
let class =
Class::try_from(CLASS).map_err(|_| SerializeError::InvalidClass { class: CLASS })?;
let mut v = Vec::new();
let inner_len = self.inner.write_der_content(&mut v)?;
let constructed = matches!(TAG, 16 | 17);
let header = Header::new(class, constructed, self.tag(), Length::Definite(inner_len));
let sz = header.write_der_header(writer)?;
let sz = sz + writer.write(&v)?;
Ok(sz)
}
fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
let mut sink = std::io::sink();
let class =
Class::try_from(CLASS).map_err(|_| SerializeError::InvalidClass { class: CLASS })?;
let inner_len = self.inner.write_der_content(&mut sink)?;
let constructed = matches!(TAG, 16 | 17);
let header = Header::new(class, constructed, self.tag(), Length::Definite(inner_len));
header.write_der_header(writer).map_err(Into::into)
}
fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
self.inner.write_der(writer)
}
}
pub type TaggedImplicit<T, E, const TAG: u32> = TaggedValue<T, E, Implicit, CONTEXT_SPECIFIC, TAG>;
impl<'a, T, E> FromBer<'a, E> for TaggedParser<'a, Implicit, T, E>
where
T: TryFrom<Any<'a>, Error = E>,
T: Tagged,
E: From<Error>,
{
fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, E> {
let (rem, any) = Any::from_ber(bytes).map_err(Err::convert)?;
let Any { header, data } = any;
let any = Any {
header: Header {
tag: T::TAG,
..header.clone()
},
data,
};
match T::try_from(any) {
Ok(t) => {
let tagged_value = TaggedParser {
header,
inner: t,
tag_kind: PhantomData,
_e: PhantomData,
};
Ok((rem, tagged_value))
}
Err(e) => Err(nom::Err::Error(e)),
}
}
}
impl<'a, T, E> TaggedParser<'a, Implicit, T, E> {
pub const fn new_implicit(class: Class, constructed: bool, tag: u32, inner: T) -> Self {
Self {
header: Header::new(class, constructed, Tag(tag), Length::Definite(0)),
inner,
tag_kind: PhantomData,
_e: PhantomData,
}
}
}
impl<'a, T, E> FromDer<'a, E> for TaggedParser<'a, Implicit, T, E>
where
T: TryFrom<Any<'a>, Error = E>,
T: CheckDerConstraints,
T: Tagged,
E: From<Error>,
{
fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E> {
let (rem, any) = Any::from_der(bytes).map_err(Err::convert)?;
let Any { header, data } = any;
let any = Any {
header: Header {
tag: T::TAG,
..header.clone()
},
data,
};
T::check_constraints(&any).map_err(|e| nom::Err::Error(e.into()))?;
match T::try_from(any) {
Ok(t) => {
let tagged_value = TaggedParser {
header,
inner: t,
tag_kind: PhantomData,
_e: PhantomData,
};
Ok((rem, tagged_value))
}
Err(e) => Err(nom::Err::Error(e)),
}
}
}
impl<'a, T> CheckDerConstraints for TaggedParser<'a, Implicit, T>
where
T: CheckDerConstraints,
T: Tagged,
{
fn check_constraints(any: &Any) -> Result<()> {
any.header.length.assert_definite()?;
let any = Any {
header: Header {
tag: T::TAG,
..any.header.clone()
},
data: any.data,
};
T::check_constraints(&any)?;
Ok(())
}
}
#[cfg(feature = "std")]
impl<'a, T> ToDer for TaggedParser<'a, Implicit, T>
where
T: ToDer,
{
fn to_der_len(&self) -> Result<usize> {
self.inner.to_der_len()
}
fn write_der(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
let mut v = Vec::new();
let inner_len = self.inner.write_der_content(&mut v)?;
let header = Header::new(self.class(), false, self.tag(), Length::Definite(inner_len));
let sz = header.write_der_header(writer)?;
let sz = sz + writer.write(&v)?;
Ok(sz)
}
fn write_der_header(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
let mut sink = std::io::sink();
let inner_len = self.inner.write_der_content(&mut sink)?;
let header = Header::new(self.class(), false, self.tag(), Length::Definite(inner_len));
header.write_der_header(writer).map_err(Into::into)
}
fn write_der_content(&self, writer: &mut dyn std::io::Write) -> SerializeResult<usize> {
self.inner.write_der_content(writer)
}
}