use crate::debug::{trace, trace_generic};
use crate::error::*;
use crate::{parse_der_any, Any, Class, Explicit, Implicit, Tag, TaggedParser};
use core::convert::{TryFrom, TryInto};
use core::fmt::{Debug, Display};
#[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, E = Error>: Sized {
fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, Self, E>;
}
impl<'a, T, E> FromBer<'a, E> for T
where
T: TryFrom<Any<'a>, Error = E>,
E: From<Error>,
{
fn from_ber(bytes: &'a [u8]) -> ParseResult<'a, T, E> {
let (i, any) = Any::from_ber(bytes).map_err(nom::Err::convert)?;
let result = any.try_into().map_err(nom::Err::Error)?;
Ok((i, result))
}
}
pub trait FromDer<'a, E = Error>: Sized {
fn from_der(bytes: &'a [u8]) -> ParseResult<'a, Self, E>;
}
pub trait DerAutoDerive {}
impl<'a, T, E> FromDer<'a, E> for T
where
T: TryFrom<Any<'a>, Error = E>,
T: CheckDerConstraints,
T: DerAutoDerive,
E: From<Error> + Display + Debug,
{
fn from_der(bytes: &'a [u8]) -> ParseResult<'a, T, E> {
trace_generic(
core::any::type_name::<T>(),
"T::from_der",
|bytes| {
let (i, any) = trace(core::any::type_name::<T>(), parse_der_any, bytes)
.map_err(nom::Err::convert)?;
<T as CheckDerConstraints>::check_constraints(&any)
.map_err(|e| nom::Err::Error(e.into()))?;
let result = any.try_into().map_err(nom::Err::Error)?;
Ok((i, result))
},
bytes,
)
}
}
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, E = Error>: Sized {
fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E> {
TaggedParser::new_explicit(class, tag, self)
}
}
impl<'a, T, E> AsTaggedExplicit<'a, E> for T where T: Sized + 'a {}
pub trait AsTaggedImplicit<'a, E = Error>: Sized {
fn implicit(
self,
class: Class,
constructed: bool,
tag: u32,
) -> TaggedParser<'a, Implicit, Self, E> {
TaggedParser::new_implicit(class, constructed, tag, self)
}
}
impl<'a, T, E> AsTaggedImplicit<'a, E> for T where T: Sized + 'a {}
pub use crate::tostatic::*;