b_x/
lib.rs

1use std::{error::Error as StdError, fmt};
2
3/// The stupidest box error ever. It's not even Send.
4///
5/// It has `From` implementations for some libstd error types,
6/// you can derive `From<E>` for your own error types
7/// with [make_bxable!]
8pub struct BX(Box<dyn StdError>);
9
10/// A type alias where `E` defaults to `BX`.
11pub type Result<T, E = BX> = std::result::Result<T, E>;
12
13impl BX {
14    /// Create a new `BX` from an `E`.
15    pub fn from_err(e: impl StdError + 'static) -> Self {
16        Self(e.into())
17    }
18
19    /// Create a new `BX` from a boxed `E`.
20    pub fn from_boxed(e: Box<dyn StdError + 'static>) -> Self {
21        Self(e)
22    }
23
24    /// Create a new `BX` from a String
25    pub fn from_string(s: String) -> Self {
26        Self(Box::new(StringError(s)))
27    }
28}
29
30pub fn box_error(e: impl StdError + 'static) -> BX {
31    BX::from_err(e)
32}
33
34/// Adds `bx() -> BX` to error types
35pub trait BxForErrors {
36    fn bx(self) -> BX;
37}
38
39impl<E: StdError + 'static> BxForErrors for E {
40    fn bx(self) -> BX {
41        BX::from_err(self)
42    }
43}
44
45/// Adds `bx() -> Result<T, BX>` to result types
46pub trait BxForResults<T> {
47    fn bx(self) -> Result<T, BX>;
48}
49
50impl<T, E: StdError + 'static> BxForResults<T> for Result<T, E> {
51    fn bx(self) -> Result<T, BX> {
52        self.map_err(BX::from_err)
53    }
54}
55
56impl fmt::Debug for BX {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        self.0.fmt(f)
59    }
60}
61
62impl fmt::Display for BX {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        self.0.fmt(f)
65    }
66}
67
68impl StdError for BX {
69    fn source(&self) -> Option<&(dyn StdError + 'static)> {
70        self.0.source()
71    }
72}
73
74/// Implements `From<E>` for `BX` for your own type.
75#[macro_export]
76macro_rules! make_bxable {
77    ($ty:ty) => {
78        impl From<$ty> for $crate::BX {
79            fn from(e: $ty) -> Self {
80                $crate::BX::from_err(e)
81            }
82        }
83    };
84}
85
86make_bxable!(std::io::Error);
87make_bxable!(std::fmt::Error);
88make_bxable!(std::str::Utf8Error);
89make_bxable!(std::string::FromUtf8Error);
90make_bxable!(std::string::FromUtf16Error);
91make_bxable!(std::num::ParseIntError);
92make_bxable!(std::num::ParseFloatError);
93make_bxable!(std::num::TryFromIntError);
94make_bxable!(std::array::TryFromSliceError);
95make_bxable!(std::char::ParseCharError);
96make_bxable!(std::net::AddrParseError);
97make_bxable!(std::time::SystemTimeError);
98make_bxable!(std::env::VarError);
99make_bxable!(std::sync::mpsc::RecvError);
100make_bxable!(std::sync::mpsc::TryRecvError);
101make_bxable!(std::sync::mpsc::SendError<Box<dyn StdError + Send + Sync>>);
102make_bxable!(std::sync::PoisonError<Box<dyn StdError + Send + Sync>>);
103
104#[macro_export]
105macro_rules! bail {
106    ($err:expr) => {
107        return Err($crate::BX::from_err($err));
108    };
109    ($fmt:expr, $($arg:tt)*) => {
110        return Err($crate::BX::from_string(format!($fmt, $($arg)*)));
111    };
112}
113
114/// The stupidest Send box error ever.
115///
116/// It has `From` implementations for some libstd error types,
117/// you can derive `From<E>` for your own error types
118pub struct BS(Box<dyn StdError + Send + Sync>);
119
120#[derive(Debug)]
121struct StringError(String);
122
123impl fmt::Display for StringError {
124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125        self.0.fmt(f)
126    }
127}
128
129impl StdError for StringError {
130    fn source(&self) -> Option<&(dyn StdError + 'static)> {
131        None
132    }
133}
134
135impl BS {
136    /// Create a new `BS` from an `E`.
137    pub fn from_err(e: impl StdError + Send + Sync + 'static) -> Self {
138        Self(Box::new(e))
139    }
140
141    /// Create a new `BS` from a boxed `E`.
142    pub fn from_boxed(e: Box<dyn StdError + Send + Sync + 'static>) -> Self {
143        Self(e)
144    }
145
146    /// Create a new `BS` from a String
147    pub fn from_string(s: String) -> Self {
148        Self(Box::new(StringError(s)))
149    }
150}
151
152pub fn box_send_error(e: impl StdError + Send + Sync + 'static) -> BS {
153    BS::from_err(e)
154}
155
156/// Adds `bs() -> BS` to error types
157pub trait BsForErrors {
158    fn bs(self) -> BS;
159}
160
161impl<E: StdError + Send + Sync + 'static> BsForErrors for E {
162    fn bs(self) -> BS {
163        BS::from_err(self)
164    }
165}
166
167/// Adds `bs() -> Result<T, BS>` to result types
168pub trait BsForResults<T> {
169    fn bs(self) -> Result<T, BS>;
170}
171
172impl<T, E: StdError + Send + Sync + 'static> BsForResults<T> for Result<T, E> {
173    fn bs(self) -> Result<T, BS> {
174        self.map_err(BS::from_err)
175    }
176}
177
178impl fmt::Debug for BS {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        self.0.fmt(f)
181    }
182}
183
184impl fmt::Display for BS {
185    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186        self.0.fmt(f)
187    }
188}
189
190impl StdError for BS {
191    fn source(&self) -> Option<&(dyn StdError + 'static)> {
192        self.0.source()
193    }
194}
195
196#[macro_export]
197macro_rules! make_bsable {
198    ($ty:ty) => {
199        impl From<$ty> for $crate::BS {
200            fn from(e: $ty) -> Self {
201                $crate::BS::from_err(e)
202            }
203        }
204    };
205}
206
207make_bsable!(std::io::Error);
208make_bsable!(std::fmt::Error);
209make_bsable!(std::str::Utf8Error);
210make_bsable!(std::string::FromUtf8Error);
211make_bsable!(std::string::FromUtf16Error);
212make_bsable!(std::num::ParseIntError);
213make_bsable!(std::num::ParseFloatError);
214make_bsable!(std::num::TryFromIntError);
215make_bsable!(std::array::TryFromSliceError);
216make_bsable!(std::char::ParseCharError);
217make_bsable!(std::net::AddrParseError);
218make_bsable!(std::time::SystemTimeError);
219make_bsable!(std::env::VarError);
220make_bsable!(std::sync::mpsc::RecvError);
221make_bsable!(std::sync::mpsc::TryRecvError);
222make_bsable!(std::sync::mpsc::SendError<Box<dyn StdError + Send + Sync>>);
223make_bsable!(std::sync::PoisonError<Box<dyn StdError + Send + Sync>>);