1use core::fmt;
2
3#[derive(Clone, Copy, Debug)]
5pub struct Error {
6 kind: Kind,
7 msg: Option<&'static str>,
8 source: Option<SourceError>,
9}
10
11impl Error {
12 pub(crate) fn new<S: AsRef<str> + ?Sized + 'static>(
13 kind: Kind,
14 msg: Option<&'static S>,
15 source: Option<SourceError>,
16 ) -> Self {
17 Self {
18 kind,
19 msg: msg.map(S::as_ref),
20 source,
21 }
22 }
23
24 #[must_use]
35 pub const fn kind(&self) -> Kind {
36 self.kind
37 }
38}
39
40impl fmt::Display for Error {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 if let Some(msg) = self.msg {
43 write!(f, "{}: {}", self.kind, msg)
44 } else {
45 self.kind.fmt(f)
46 }
47 }
48}
49
50#[cfg(feature = "std")]
51#[allow(trivial_casts)]
52impl std::error::Error for Error {
53 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
54 self.source.map(|err| err as _)
55 }
56}
57
58#[cfg(not(feature = "std"))]
59impl Error {
60 #[must_use]
65 pub fn source(&self) -> Option<SourceError> {
66 self.source
67 }
68}
69
70#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
72pub enum Kind {
73 PrefixLength,
75 ParserError,
77 AfiMismatch,
80 PrefixLengthRange,
82 OctetSliceOverrun,
85}
86
87impl fmt::Display for Kind {
88 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
89 match self {
90 Self::PrefixLength => {
91 write!(f, "prefix-length out of bounds")
92 }
93 Self::ParserError => write!(f, "parser error"),
94 Self::AfiMismatch => write!(f, "address family mis-match"),
95 Self::PrefixLengthRange => write!(f, "invalid prefix-length range"),
96 Self::OctetSliceOverrun => write!(f, "octet slice too long for address-family"),
97 }
98 }
99}
100
101#[cfg(feature = "std")]
102type SourceError = &'static (dyn std::error::Error + Send + Sync + 'static);
103#[cfg(not(feature = "std"))]
104type SourceError = &'static (dyn core::any::Any);
105
106macro_rules! err {
107 ( $kind:expr ) => {
108 $crate::error::Error::new::<&'static str>($kind, None, None)
109 };
110 ( $kind:expr, $msg:expr ) => {
111 $crate::error::Error::new($kind, Some($msg), None)
112 };
113}
114pub(crate) use err;
115
116#[cfg(test)]
117pub(crate) type TestResult = Result<(), Error>;