1#![cfg_attr(not(feature = "std"), no_std)]
21extern crate alloc;
22
23use core::fmt;
24
25use anyhow::Error as AnyError;
26
27#[cold]
28pub const fn cold() {}
29pub const fn likely(b: bool) -> bool {
30 if !b {
31 cold()
32 }
33 b
34}
35pub const fn unlikely(b: bool) -> bool {
36 if b {
37 cold()
38 }
39 b
40}
41
42#[cfg(not(feature = "std"))]
43use alloc::boxed::Box;
44#[cfg(not(feature = "std"))]
45use core::any::Any;
46
47#[cfg(not(feature = "std"))]
52pub trait IError: fmt::Display + fmt::Debug + Any {}
53#[cfg(not(feature = "std"))]
57impl dyn IError {
58 pub fn is<T: 'static>(&self) -> bool {
59 Any::type_id(self) == core::any::TypeId::of::<T>()
60 }
61 pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
62 self.is::<T>()
63 .then(|| unsafe { &*(self as *const dyn IError as *const T) })
64 }
65}
66
67#[cfg(not(feature = "std"))]
68impl dyn IError + Send {
69 pub fn is<T: 'static>(&self) -> bool {
70 Any::type_id(self) == core::any::TypeId::of::<T>()
71 }
72 pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
73 self.is::<T>()
74 .then(|| unsafe { &*(self as *const dyn IError as *const T) })
75 }
76}
77
78#[cfg(not(feature = "std"))]
79impl dyn IError + Send + Sync {
80 pub fn is<T: 'static>(&self) -> bool {
81 Any::type_id(self) == core::any::TypeId::of::<T>()
82 }
83 pub fn downcast_ref<T: 'static>(&self) -> Option<&T> {
84 self.is::<T>()
85 .then(|| unsafe { &*(self as *const dyn IError as *const T) })
86 }
87}
88
89#[cfg(feature = "std")]
90pub use std::error::Error as IError;
91
92pub type Error = Box<dyn IError + Send + Sync + 'static>;
93
94pub type ZResult<T> = core::result::Result<T, Error>;
99
100#[repr(transparent)]
105#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
106pub struct NegativeI8(i8);
107
108impl NegativeI8 {
109 pub const fn new(v: i8) -> Self {
110 if v >= 0 {
111 panic!("Non-negative value used in NegativeI8")
112 }
113 NegativeI8(v)
114 }
115 pub const fn get(self) -> i8 {
116 self.0
117 }
118 pub const MIN: Self = Self::new(i8::MIN);
119}
120
121pub struct ZError {
122 error: AnyError,
123 file: &'static str,
124 line: u32,
125 errno: NegativeI8,
126 source: Option<Error>,
127}
128
129unsafe impl Send for ZError {}
130unsafe impl Sync for ZError {}
131
132impl ZError {
133 pub fn new<E: Into<AnyError>>(
134 error: E,
135 file: &'static str,
136 line: u32,
137 errno: NegativeI8,
138 ) -> ZError {
139 ZError {
140 error: error.into(),
141 file,
142 line,
143 errno,
144 source: None,
145 }
146 }
147 pub fn set_source<S: Into<Error>>(mut self, source: S) -> Self {
148 self.source = Some(source.into());
149 self
150 }
151}
152
153#[cfg(feature = "std")]
154impl std::error::Error for ZError {
155 fn source(&self) -> Option<&'_ (dyn std::error::Error + 'static)> {
156 self.source
157 .as_ref()
158 .map(|r| unsafe { core::mem::transmute(r.as_ref()) })
159 }
160}
161
162#[cfg(not(feature = "std"))]
163impl IError for ZError {}
164
165impl fmt::Debug for ZError {
166 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
167 fmt::Display::fmt(&self, f)
168 }
169}
170
171impl fmt::Display for ZError {
172 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173 write!(f, "{} at {}:{}.", self.error, self.file, self.line)?;
174 if let Some(s) = &self.source {
175 write!(f, " - Caused by {}", *s)?;
176 }
177 Ok(())
178 }
179}
180
181#[cfg(not(feature = "std"))]
182impl From<ZError> for Error {
183 fn from(value: ZError) -> Self {
184 Box::new(value)
185 }
186}
187
188#[derive(Debug)]
193pub struct ShmError(pub ZError);
194
195#[cfg(feature = "std")]
196impl std::error::Error for ShmError {
197 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
198 self.0.source()
199 }
200}
201
202#[cfg(not(feature = "std"))]
203impl IError for ShmError {}
204
205impl fmt::Display for ShmError {
206 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
207 self.0.fmt(f)
208 }
209}
210
211#[cfg(not(feature = "std"))]
212impl From<ShmError> for Error {
213 fn from(value: ShmError) -> Self {
214 Box::new(value)
215 }
216}
217
218pub trait ErrNo {
223 fn errno(&self) -> NegativeI8;
224}
225
226impl ErrNo for ZError {
227 fn errno(&self) -> NegativeI8 {
228 self.errno
229 }
230}
231
232impl ErrNo for ShmError {
233 fn errno(&self) -> NegativeI8 {
234 self.0.errno
235 }
236}
237
238#[cfg(feature = "std")]
239impl ErrNo for dyn std::error::Error {
240 fn errno(&self) -> NegativeI8 {
241 match self.downcast_ref::<ZError>() {
242 Some(e) => e.errno(),
243 None => NegativeI8::new(i8::MIN),
244 }
245 }
246}
247
248#[cfg(not(feature = "std"))]
249impl ErrNo for dyn IError {
250 fn errno(&self) -> NegativeI8 {
251 match self.downcast_ref::<ZError>() {
252 Some(e) => e.errno(),
253 None => NegativeI8::new(i8::MIN),
254 }
255 }
256}
257
258#[cfg(feature = "std")]
259impl ErrNo for dyn std::error::Error + Send {
260 fn errno(&self) -> NegativeI8 {
261 match self.downcast_ref::<ZError>() {
262 Some(e) => e.errno(),
263 None => NegativeI8::new(i8::MIN),
264 }
265 }
266}
267
268#[cfg(not(feature = "std"))]
269impl ErrNo for dyn IError + Send {
270 fn errno(&self) -> NegativeI8 {
271 match self.downcast_ref::<ZError>() {
272 Some(e) => e.errno(),
273 None => NegativeI8::new(i8::MIN),
274 }
275 }
276}
277
278#[cfg(feature = "std")]
279impl ErrNo for dyn std::error::Error + Send + Sync {
280 fn errno(&self) -> NegativeI8 {
281 match self.downcast_ref::<ZError>() {
282 Some(e) => e.errno(),
283 None => NegativeI8::new(i8::MIN),
284 }
285 }
286}
287
288#[cfg(not(feature = "std"))]
289impl ErrNo for dyn IError + Send + Sync {
290 fn errno(&self) -> NegativeI8 {
291 match self.downcast_ref::<ZError>() {
292 Some(e) => e.errno(),
293 None => NegativeI8::new(i8::MIN),
294 }
295 }
296}
297
298pub use anyhow::anyhow;
303#[macro_export]
304macro_rules! zerror {
305 (($errno:expr) $source: expr => $($t: tt)*) => {
306 $crate::ZError::new($crate::anyhow!($($t)*), file!(), line!(), $crate::NegativeI8::new($errno as i8)).set_source($source)
307 };
308 (($errno:expr) $t: literal) => {
309 $crate::ZError::new($crate::anyhow!($t), file!(), line!(), $crate::NegativeI8::new($errno as i8))
310 };
311 (($errno:expr) $t: expr) => {
312 $crate::ZError::new($t, file!(), line!(), $crate::NegativeI8::new($errno as i8))
313 };
314 (($errno:expr) $($t: tt)*) => {
315 $crate::ZError::new($crate::anyhow!($($t)*), file!(), line!(), $crate::NegativeI8::new($errno as i8))
316 };
317 ($source: expr => $($t: tt)*) => {
318 $crate::ZError::new($crate::anyhow!($($t)*), file!(), line!(), $crate::NegativeI8::MIN).set_source($source)
319 };
320 ($t: literal) => {
321 $crate::ZError::new($crate::anyhow!($t), file!(), line!(), $crate::NegativeI8::MIN)
322 };
323 ($t: expr) => {
324 $crate::ZError::new($t, file!(), line!(), $crate::NegativeI8::MIN)
325 };
326 ($($t: tt)*) => {
327 $crate::ZError::new($crate::anyhow!($($t)*), file!(), line!(), $crate::NegativeI8::MIN)
328 };
329}
330
331#[macro_export]
334macro_rules! bail{
335 ($($t: tt)*) => {
336 return Err($crate::zerror!($($t)*).into())
337 };
338}
339
340#[macro_export]
342macro_rules! to_zerror {
343 ($kind:ident, $descr:expr) => {
344 |e| Err(zerror!($kind, $descr, e))
345 };
346}