use crate::error::*;
use crate::{Any, Class, Explicit, Implicit, Tag, TaggedParser};
use core::convert::{TryFrom, TryInto};
#[cfg(feature = "std")]
use std::io::Write;
#[doc(hidden)]
#[derive(Debug)]
pub enum BerParser {}
#[doc(hidden)]
#[derive(Debug)]
pub enum DerParser {}
#[doc(hidden)]
pub trait ASN1Parser {}
impl ASN1Parser for BerParser {}
impl ASN1Parser for DerParser {}
pub trait Tagged {
const TAG: Tag;
}
impl<T> Tagged for &'_ T
where
T: Tagged,
{
const TAG: Tag = T::TAG;
}
pub trait DynTagged {
fn tag(&self) -> Tag;
}
impl<T> DynTagged for T
where
T: Tagged,
{
fn tag(&self) -> Tag {
T::TAG
}
}
pub trait FromBer<'a>: Sized {
fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self>;
}
impl<'a, T> FromBer<'a> for T
where
T: TryFrom<Any<'a>, Error = Error>,
{
fn from_ber(bytes: &'a [u8]) -> ParseResult<T> {
let (i, any) = Any::from_ber(bytes)?;
let result = any.try_into().map_err(nom::Err::Error)?;
Ok((i, result))
}
}
pub trait FromDer<'a>: Sized {
fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self>;
}
impl<'a, T> FromDer<'a> for T
where
T: TryFrom<Any<'a>, Error = Error>,
T: CheckDerConstraints,
{
fn from_der(bytes: &'a [u8]) -> ParseResult<T> {
let (i, any) = Any::from_der(bytes)?;
if !any.header.length.is_definite() {
return Err(nom::Err::Error(Error::DerConstraintFailed(
DerConstraint::IndefiniteLength,
)));
}
<T as CheckDerConstraints>::check_constraints(&any).map_err(nom::Err::Error)?;
let result = any.try_into().map_err(nom::Err::Error)?;
Ok((i, result))
}
}
pub trait CheckDerConstraints {
fn check_constraints(any: &Any) -> Result<()>;
}
#[cfg(feature = "std")]
pub trait ToDer
where
Self: DynTagged,
{
fn to_der_len(&self) -> Result<usize>;
fn to_der_vec(&self) -> SerializeResult<Vec<u8>> {
let mut v = Vec::new();
let _ = self.write_der(&mut v)?;
Ok(v)
}
fn to_der_vec_raw(&self) -> SerializeResult<Vec<u8>> {
let mut v = Vec::new();
let _ = self.write_der_raw(&mut v)?;
Ok(v)
}
fn write_der(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
let sz = self.write_der_header(writer)?;
let sz = sz + self.write_der_content(writer)?;
Ok(sz)
}
fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize>;
fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize>;
fn write_der_raw(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
self.write_der(writer)
}
}
#[cfg(feature = "std")]
impl<'a, T> ToDer for &'a T
where
T: ToDer,
&'a T: DynTagged,
{
fn to_der_len(&self) -> Result<usize> {
(*self).to_der_len()
}
fn write_der_header(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
(*self).write_der_header(writer)
}
fn write_der_content(&self, writer: &mut dyn Write) -> SerializeResult<usize> {
(*self).write_der_content(writer)
}
}
pub trait AsTaggedExplicit<'a>: Sized {
fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self> {
TaggedParser::new_explicit(class, tag, self)
}
}
impl<'a, T> AsTaggedExplicit<'a> for T where T: Sized + 'a {}
pub trait AsTaggedImplicit<'a>: Sized {
fn implicit(
self,
class: Class,
constructed: bool,
tag: u32,
) -> TaggedParser<'a, Implicit, Self> {
TaggedParser::new_implicit(class, constructed, tag, self)
}
}
impl<'a, T> AsTaggedImplicit<'a> for T where T: Sized + 'a {}
pub trait ToStatic {
type Owned: 'static;
fn to_static(&self) -> Self::Owned;
}