1use core::fmt::{Debug, Display, Formatter};
4
5#[macro_export]
7macro_rules! err {
8 ($variant:expr, $desc:expr) => {{
9 $crate::error::Error::new($variant, $desc, file!(), line!())
10 }};
11}
12
13#[derive(Debug, Clone)]
15pub struct Error<Variant> {
16 pub variant: Variant,
18 #[cfg(feature = "backtrace")]
20 pub description: &'static str,
21 #[cfg(feature = "backtrace")]
23 pub file: &'static str,
24 #[cfg(feature = "backtrace")]
26 pub line: u32,
27 #[cfg(all(feature = "backtrace", feature = "std"))]
29 pub backtrace: std::sync::Arc<std::backtrace::Backtrace>,
30}
31impl<Variant> Error<Variant> {
32 #[doc(hidden)]
34 #[allow(unused, reason = "some args are unused, depending on feature flags")]
35 pub fn new(variant: Variant, description: &'static str, file: &'static str, line: u32) -> Self {
36 Self {
37 variant,
38 #[cfg(feature = "backtrace")]
39 description,
40 #[cfg(feature = "backtrace")]
41 file,
42 #[cfg(feature = "backtrace")]
43 line,
44 #[cfg(all(feature = "backtrace", feature = "std"))]
45 backtrace: std::sync::Arc::new(std::backtrace::Backtrace::capture()),
46 }
47 }
48
49 pub fn into_variant<NewVariant>(self, new_variant: NewVariant) -> Error<NewVariant> {
51 Error {
52 variant: new_variant,
53 #[cfg(feature = "backtrace")]
54 description: self.description,
55 #[cfg(feature = "backtrace")]
56 file: self.file,
57 #[cfg(feature = "backtrace")]
58 line: self.line,
59 #[cfg(all(feature = "backtrace", feature = "std"))]
60 backtrace: self.backtrace,
61 }
62 }
63}
64impl<T> Display for Error<T>
65where
66 T: Debug,
67{
68 #[cfg(not(feature = "backtrace"))]
69 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
70 write!(f, "MQTT error: {:#?}", self.variant)
71 }
72
73 #[cfg(all(feature = "backtrace", not(feature = "std")))]
74 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
75 write!(f, "MQTT error: {:#?} at {}:{}", self.variant, self.file, self.line)
76 }
77
78 #[cfg(all(feature = "backtrace", feature = "std"))]
79 fn fmt(&self, f: &mut Formatter) -> core::fmt::Result {
80 use std::backtrace::BacktraceStatus;
81
82 write!(f, "MQTT error: {:#?} at", self.variant)?;
83 if self.backtrace.status() == BacktraceStatus::Captured {
84 writeln!(f, "{}", self.backtrace)?;
86 }
87
88 Ok(())
89 }
90}
91#[cfg(feature = "std")]
92impl<T> std::error::Error for Error<T>
93where
94 T: Debug,
95{
96 }
98
99#[derive(Debug, Clone, PartialEq, Eq)]
101pub struct Memory;
102
103#[derive(Debug, Clone, PartialEq, Eq)]
105pub enum Data {
106 Truncated,
108 SpecViolation,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq)]
114pub enum Decoding {
115 Truncated,
117 SpecViolation,
119 Memory,
121}
122impl From<Error<Memory>> for Error<Decoding> {
123 fn from(error: Error<Memory>) -> Self {
124 error.into_variant(Decoding::Memory)
125 }
126}
127impl From<Error<Data>> for Error<Decoding> {
128 fn from(error: Error<Data>) -> Self {
129 match error.variant {
130 Data::Truncated => error.into_variant(Decoding::Truncated),
131 Data::SpecViolation => error.into_variant(Decoding::SpecViolation),
132 }
133 }
134}
135
136pub type MemoryError = Error<Memory>;
138
139pub type DataError = Error<Data>;
141
142pub type DecoderError = Error<Decoding>;