1#![warn(missing_docs)]
4#![cfg_attr(
5 feature = "unstable-error-generic-member-access",
6 feature(error_generic_member_access)
7)]
8#![cfg_attr(
12 feature = "unstable-error-generic-member-access",
13 doc(test(attr(feature(error_generic_member_access))))
14)]
15
16mod backtrace;
17mod chain;
18mod diagnostic;
19#[cfg(feature = "serde")]
20pub mod erased;
21#[cfg(feature = "extras")]
22pub mod extras;
23mod marker;
24mod spantrace;
25#[cfg(feature = "test-utils")]
26pub mod test_utils;
27mod traits;
28mod welp;
29
30use std::borrow::{Borrow, Cow};
31use std::ops::Deref;
32
33pub use backtrace::{
34 Backtrace, RustBacktrace, clear_rust_backtrace_override, rust_backtrace, rust_panic_backtrace,
35 set_rust_backtrace_override, with_rust_backtrace_override,
36};
37pub use chain::{Chain, ErrorChainExt};
38pub use diagnostic::Diagnostic;
39pub use spantrace::{OptionalSpanTrace, SpanTrace};
40#[cfg(feature = "tracing")]
41pub mod tracing;
42
43pub use traits::*;
44pub use welp::{Welp, WelpOptionExt, WelpResultExt};
45#[doc(hidden)]
47pub mod __private {
48 pub use crate::backtrace::CORE_SRC_PATH;
49 pub struct CaptureProbe<'a, T: ?Sized>(pub &'a T);
56
57 pub trait CaptureFromExt {
59 fn resolve<C: crate::Capturable>(&self) -> C;
60 }
61
62 impl<T: crate::Diagnostic> CaptureFromExt for CaptureProbe<'_, T> {
63 #[inline]
64 #[track_caller]
65 fn resolve<C: crate::Capturable>(&self) -> C {
66 C::capture_or_extract(self.0)
67 }
68 }
69
70 pub trait CaptureFromFallback {
72 fn resolve<C: crate::Capturable>(&self) -> C;
73 }
74
75 impl<T: ?Sized> CaptureFromFallback for &CaptureProbe<'_, T> {
76 #[inline]
77 #[track_caller]
78 fn resolve<C: crate::Capturable>(&self) -> C {
79 C::capture()
80 }
81 }
82
83 pub struct DiagProbe<'a, T: ?Sized>(pub &'a T);
94
95 pub trait DiagForwardExt<'a> {
97 fn fwd_code(&self) -> Option<crate::ErrorCode>;
98 fn fwd_help(&self) -> Option<crate::HelpText>;
99 fn fwd_backtrace(&self) -> Option<&'a crate::Backtrace>;
100 fn fwd_spantrace(&self) -> Option<&'a crate::SpanTrace>;
101 fn fwd_location(&self) -> Option<&'static std::panic::Location<'static>>;
102 fn fwd_exit_code(&self) -> Option<core::num::NonZeroU8>;
103 }
104
105 impl<'a, T: crate::Diagnostic + ?Sized> DiagForwardExt<'a> for DiagProbe<'a, T> {
106 #[inline]
107 fn fwd_code(&self) -> Option<crate::ErrorCode> {
108 self.0.oopsie_error_code()
109 }
110 #[inline]
111 fn fwd_help(&self) -> Option<crate::HelpText> {
112 self.0.oopsie_help_text()
113 }
114 #[inline]
115 fn fwd_backtrace(&self) -> Option<&'a crate::Backtrace> {
116 self.0.oopsie_backtrace()
117 }
118 #[inline]
119 fn fwd_spantrace(&self) -> Option<&'a crate::SpanTrace> {
120 self.0.oopsie_spantrace()
121 }
122 #[inline]
123 fn fwd_location(&self) -> Option<&'static std::panic::Location<'static>> {
124 self.0.oopsie_location()
125 }
126 #[inline]
127 fn fwd_exit_code(&self) -> Option<core::num::NonZeroU8> {
128 self.0.oopsie_exit_code()
129 }
130 }
131
132 pub trait DiagForwardFallback<'a> {
134 #[inline]
135 fn fwd_code(&self) -> Option<crate::ErrorCode> {
136 None
137 }
138 #[inline]
139 fn fwd_help(&self) -> Option<crate::HelpText> {
140 None
141 }
142 #[inline]
143 fn fwd_backtrace(&self) -> Option<&'a crate::Backtrace> {
144 None
145 }
146 #[inline]
147 fn fwd_spantrace(&self) -> Option<&'a crate::SpanTrace> {
148 None
149 }
150 #[inline]
151 fn fwd_location(&self) -> Option<&'static std::panic::Location<'static>> {
152 None
153 }
154 #[inline]
155 fn fwd_exit_code(&self) -> Option<core::num::NonZeroU8> {
156 None
157 }
158 }
159
160 impl<'a, T: ?Sized> DiagForwardFallback<'a> for &DiagProbe<'a, T> {}
161
162 #[inline]
175 #[must_use]
176 pub fn source_trace<'a, T: 'static>(
177 source: &'a (dyn std::error::Error + 'static),
178 ) -> Option<&'a T> {
179 #[cfg(feature = "unstable-error-generic-member-access")]
180 {
181 core::error::request_ref::<T>(source)
182 }
183 #[cfg(not(feature = "unstable-error-generic-member-access"))]
184 {
185 let _ = source;
186 None
187 }
188 }
189
190 #[inline]
194 #[must_use]
195 pub fn source_backtrace<'a>(
196 source: &'a (dyn std::error::Error + 'static),
197 ) -> Option<&'a crate::Backtrace> {
198 source_trace::<crate::Backtrace>(source).filter(|bt| bt.is_captured())
199 }
200
201 #[inline]
203 #[must_use]
204 pub fn source_spantrace<'a>(
205 source: &'a (dyn std::error::Error + 'static),
206 ) -> Option<&'a crate::SpanTrace> {
207 source_trace::<crate::SpanTrace>(source).filter(|st| st.is_captured())
208 }
209
210 pub use crate::marker::{TraceMarker, restore_marker, set_marker};
211
212 #[inline]
216 #[must_use]
217 pub fn source_exit_code(
218 source: &(dyn std::error::Error + 'static),
219 ) -> Option<core::num::NonZeroU8> {
220 #[cfg(feature = "unstable-error-generic-member-access")]
221 {
222 core::error::request_value::<core::num::NonZeroU8>(source)
223 }
224 #[cfg(not(feature = "unstable-error-generic-member-access"))]
225 {
226 let _ = source;
227 None
228 }
229 }
230
231 #[inline]
235 #[must_use]
236 pub const fn nonzero_u8_unchecked(value: u8) -> core::num::NonZeroU8 {
237 match core::num::NonZeroU8::new(value) {
238 Some(n) => n,
239 None => panic!("exit code must be non-zero"),
240 }
241 }
242
243 #[cfg(feature = "chrono")]
244 pub use chrono;
245}
246
247macro_rules! impl_string_newtypes {
248 ($($(#[$meta:meta])* $ident:ident,)* $(,)?) => { $(
249 #[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
250 #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
251 #[cfg_attr(feature = "serde", serde(transparent))]
252 #[repr(transparent)]
253 $(#[$meta])*
254 pub struct $ident(Cow<'static, str>);
255
256 impl $ident {
257 #[doc = concat!("Build a new `", stringify!($ident), "` from a `&'static str`.")]
258 #[must_use]
259 #[inline]
260 pub const fn from_static(s: &'static str) -> Self {
261 Self(Cow::Borrowed(s))
262 }
263
264 #[doc = concat!("Build a new `", stringify!($ident), "` from a `String`.")]
265 #[must_use]
266 #[inline]
267 pub const fn from_string(s: String) -> Self {
268 Self(Cow::Owned(s))
269 }
270
271 #[must_use]
273 #[inline]
274 pub const fn as_str(&self) -> &str {
275 match &self.0 {
276 Cow::Borrowed(s) => s,
277 Cow::Owned(s) => s.as_str(),
278 }
279 }
280
281 #[doc = concat!("Consume the `", stringify!($ident), "` and return the underlying `Cow`.")]
282 #[must_use]
283 #[inline]
284 pub fn into_inner(self) -> Cow<'static, str> {
285 self.0
286 }
287 }
288
289 impl Deref for $ident {
290 type Target = str;
291
292 #[inline]
293 fn deref(&self) -> &Self::Target {
294 self.as_str()
295 }
296 }
297
298 impl Borrow<str> for $ident {
299 #[inline]
300 fn borrow(&self) -> &str {
301 self.as_str()
302 }
303 }
304
305 impl From<&'static str> for $ident {
306 #[inline]
307 fn from(s: &'static str) -> Self {
308 Self::from_static(s)
309 }
310 }
311
312 impl From<String> for $ident {
313 #[inline]
314 fn from(s: String) -> Self {
315 Self::from_string(s)
316 }
317 }
318
319 impl std::fmt::Display for $ident {
320 #[inline]
321 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
322 self.0.fmt(f)
323 }
324 }
325
326 )* };
327}
328
329impl_string_newtypes!(
330 ErrorCode,
332 HelpText,
334);