use core::fmt::{self, Display, Formatter};
#[cfg(feature = "std")]
use std::error::Error;
#[doc(hidden)]
#[macro_export]
macro_rules! e {
() => {
concat!("@", file!(), ":", line!())
};
($str:expr) => {
concat!($str, " @", file!(), ":", line!())
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! eio {
($str:expr) => {
$crate::error::Asn1DerError::new($crate::error::Asn1DerErrorVariant::InOutError(e!($str)))
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! einval {
($str:expr) => {
$crate::error::Asn1DerError::new($crate::error::Asn1DerErrorVariant::InvalidData(e!($str)))
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! eunsupported {
($str:expr) => {
$crate::error::Asn1DerError::new($crate::error::Asn1DerErrorVariant::Unsupported(e!($str)))
};
}
#[doc(hidden)]
#[macro_export]
macro_rules! eother {
($str:expr) => {
$crate::error::Asn1DerError::new($crate::error::Asn1DerErrorVariant::Other(e!($str)))
};
}
pub trait ErrorChain {
fn propagate(self, desc: &'static str) -> Self;
}
impl<T> ErrorChain for Result<T, Asn1DerError> {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn propagate(self, _desc: &'static str) -> Self {
#[cfg(any(not(feature = "std"), feature = "no_panic"))]
return self;
#[cfg(all(feature = "std", not(feature = "no_panic")))]
{
self.map_err(|e| {
let new_error = match e.error {
Asn1DerErrorVariant::InOutError(_) => Asn1DerErrorVariant::InOutError(_desc),
Asn1DerErrorVariant::InvalidData(_) => Asn1DerErrorVariant::InvalidData(_desc),
Asn1DerErrorVariant::Unsupported(_) => Asn1DerErrorVariant::Unsupported(_desc),
Asn1DerErrorVariant::Other(_) => Asn1DerErrorVariant::Other(_desc),
};
Asn1DerError { error: new_error, source: Some(ErrorSource::new(e)) }
})
}
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum Asn1DerErrorVariant {
InOutError(&'static str),
InvalidData(&'static str),
Unsupported(&'static str),
Other(&'static str),
}
impl Display for Asn1DerErrorVariant {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self {
Asn1DerErrorVariant::InOutError(desc) => write!(f, "I/O error {}", desc),
Asn1DerErrorVariant::InvalidData(desc) => write!(f, "Invalid encoding {}", desc),
Asn1DerErrorVariant::Unsupported(desc) => write!(f, "Unsupported {}", desc),
Asn1DerErrorVariant::Other(desc) => write!(f, "Other {}", desc),
}
}
}
#[doc(hidden)]
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ErrorSource {
#[cfg(any(not(feature = "std"), feature = "no_panic"))]
inner: &'static str,
#[cfg(all(feature = "std", not(feature = "no_panic")))]
inner: Box<Asn1DerError>,
}
impl ErrorSource {
#[cfg(all(feature = "std", not(feature = "no_panic")))]
pub fn new(e: Asn1DerError) -> Self {
Self { inner: Box::new(e) }
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Asn1DerError {
#[doc(hidden)]
pub error: Asn1DerErrorVariant,
#[doc(hidden)]
pub source: Option<ErrorSource>,
}
impl Asn1DerError {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
pub fn new(variant: Asn1DerErrorVariant) -> Self {
Self { error: variant, source: None }
}
}
impl Display for Asn1DerError {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
match self.source.as_ref() {
Some(source) => write!(f, "{}\n caused by: {}", self.error, source.inner),
None => write!(f, "{}", self.error),
}
}
}
#[cfg(feature = "std")]
impl Error for Asn1DerError {
#[cfg_attr(feature = "no_panic", no_panic::no_panic)]
fn source(&self) -> Option<&(dyn Error + 'static)> {
#[cfg(any(not(feature = "std"), feature = "no_panic"))]
return None;
#[cfg(all(feature = "std", not(feature = "no_panic")))]
return self.source.as_ref().map(|s| s.inner.as_ref() as _);
}
}