use core::fmt;
#[derive(Clone, Copy, Debug)]
pub struct Error {
kind: Kind,
msg: Option<&'static str>,
source: Option<SourceError>,
}
impl Error {
pub(crate) fn new<S: AsRef<str> + ?Sized + 'static>(
kind: Kind,
msg: Option<&'static S>,
source: Option<SourceError>,
) -> Self {
Self {
kind,
msg: msg.map(S::as_ref),
source,
}
}
#[must_use]
pub const fn kind(&self) -> Kind {
self.kind
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(msg) = self.msg {
write!(f, "{}: {}", self.kind, msg)
} else {
self.kind.fmt(f)
}
}
}
#[cfg(feature = "std")]
#[allow(trivial_casts)]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.source.map(|err| err as _)
}
}
#[cfg(not(feature = "std"))]
impl Error {
#[must_use]
pub fn source(&self) -> Option<SourceError> {
self.source
}
}
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
pub enum Kind {
PrefixLength,
ParserError,
AfiMismatch,
PrefixLengthRange,
}
impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::PrefixLength => {
write!(f, "prefix-length out of bounds")
}
Self::ParserError => write!(f, "parser error"),
Self::AfiMismatch => write!(f, "address family mis-match"),
Self::PrefixLengthRange => write!(f, "invalid prefix-length range"),
}
}
}
#[cfg(feature = "std")]
type SourceError = &'static (dyn std::error::Error + Send + Sync + 'static);
#[cfg(not(feature = "std"))]
type SourceError = &'static (dyn core::any::Any);
macro_rules! err {
( $kind:expr ) => {
$crate::error::Error::new::<&'static str>($kind, None, None)
};
( $kind:expr, $msg:expr ) => {
$crate::error::Error::new($kind, Some($msg), None)
};
}
pub(crate) use err;
#[cfg(test)]
pub(crate) type TestResult = Result<(), Error>;