1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
// Copyright (C) 2025-2026 Takayuki Sato. All Rights Reserved.
// This program is free software under MIT License.
// See the file LICENSE in this distribution for more details.
//! This crate is for error handling in Rust programs, providing an `Err` struct which represents
//! an error with a reason.
//!
//! The type of this reason is any, but typically an enum variant is used.
//! The name of this enum variant indicates the reason for the error, and its fields store
//! contextual information about the situation in which the error occurred.
//! Since the path of an enum variant, including its package, is unique within a program, the enum
//! variant representing the reason is useful for identifying the specific error, locating where it
//! occurred, or generating appropriate error messages, etc.
//!
//! Optionally, by using `notify` feature and registering error handlers in advance, it is
//! possible to receive notifications either synchronously or asynchronously at the time the error
//! struct is created.
//!
//! There is also an `notify-tokio` feature, which is for applications that use the Tokio
//! runtime. If this feature is used, error notifications are received by asynchronous handlers
//! running on the Tokio runtime.
//!
//! ## Install
//!
//! In `Cargo.toml`, write this crate as a dependency:
//!
//! ```toml
//! [dependencies]
//! errs = "0.8.2"
//! ```
//!
//! If you want to use error notification, specify `notify` or `notify-tokio` in the
//! dependency features. The `notify` feature is for general use, while the
//! `notify-tokio` feature is for use with the Tokio runtime.
//!
//! ```toml
//! [dependencies]
//! errs = { version = "0.8.2", features = ["notify"] }
//! ```
//!
//! If you are using Tokio, you should specify `notify-tokio`:
//!
//! ```toml
//! [dependencies]
//! errs = { version = "0.8.2", features = ["notify-tokio"] }
//! ```
//!
//! ## Usage
//!
//! ### Err instantiation and identification of a reason
//!
//! The `Err` struct can be instantiated with `new<R>(reason: R)` function or
//! `with_source<R, E>(reason: R, source: E)` function.
//!
//! Then, the reason can be identified with `reason<R>(&self)` method and a `match` statement,
//! or `match_reason<R>(&self, func fn(&R))` method.
//!
//! The following code is an example which uses `new<R>(reason: R)` function for instantiation,
//! and `reason<R>(&self)` method and a `match` statement for identifying a reason:
//!
//! ```
//! use errs::Err;
//!
//! #[derive(Debug)]
//! enum Reasons {
//! IllegalState { state: String },
//! // ...
//! }
//!
//! let err = Err::new(Reasons::IllegalState { state: "bad state".to_string() });
//!
//! match err.reason::<Reasons>() {
//! Ok(r) => match r {
//! Reasons::IllegalState { state } => println!("state = {state}"),
//! _ => { /* ... */ }
//! }
//! Err(err) => match err.reason::<String>() {
//! Ok(s) => println!("string reason = {s}"),
//! Err(err) => { /* ... */ }
//! }
//! }
//! ```
//!
//! ### Macro-based Registration of Err Handlers
//!
//! In addition to function-based handler registration, this crate provides macros for
//! registering error handlers from a static context (e.g., outside a function body).
//! These macros utilize the `inventory` crate to collect handlers at compile time,
//! making them available for the error notification system.
//!
//! Registered handlers are activated when the `fix_err_handlers` function is called
//! or implicitly upon the first `Err` instance creation.
//!
//! #### `add_sync_err_handler!`
//! Statically registers a synchronous error handler.
//!
//! ```rust
//! #[cfg(feature = "notify")]
//! use errs::{add_sync_err_handler, Err};
//! #[cfg(feature = "notify")]
//! use chrono::{DateTime, Utc};
//!
//! #[cfg(feature = "notify")]
//! fn my_static_sync_handler(err: &Err, tm: DateTime<Utc>) {
//! println!("[Static Sync] Error at {}: {}", tm, err);
//! }
//!
//! #[cfg(feature = "notify")]
//! add_sync_err_handler!(my_static_sync_handler);
//! ```
//!
//! #### `add_async_err_handler!`
//! Statically registers a general-purpose asynchronous error handler.
//!
//! ```rust
//! #[cfg(feature = "notify")]
//! use errs::{add_async_err_handler, Err};
//! #[cfg(feature = "notify")]
//! use chrono::{DateTime, Utc};
//!
//! #[cfg(feature = "notify")]
//! fn my_static_async_handler(err: &Err, tm: DateTime<Utc>) {
//! println!("[Static Async] Error at {}: {}", tm, err);
//! }
//!
//! #[cfg(feature = "notify")]
//! add_async_err_handler!(my_static_async_handler);
//! ```
//!
//! #### `add_tokio_async_err_handler!`
//! Statically registers a Tokio-based asynchronous error handler.
//!
//! ```rust
//! #[cfg(feature = "notify-tokio")]
//! use errs::{add_tokio_async_err_handler, Err};
//! #[cfg(feature = "notify-tokio")]
//! use chrono::{DateTime, Utc};
//! use std::sync::Arc;
//!
//! #[cfg(feature = "notify-tokio")]
//! add_tokio_async_err_handler!(async |err: Arc<Err>, tm: DateTime<Utc>| {
//! tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
//! println!("[Static Tokio Async] Error at {}: {}", tm, err);
//! });
//!
//! // You can also register a function pointer:
//! // #[cfg(feature = "notify-tokio")]
//! // fn my_static_tokio_handler(err: Arc<Err>, tm: DateTime<Utc>) -> std::pin::Pin<Box<dyn std::future::Future<Output = ()> + Send>> {
//! // Box::pin(async move {
//! // println!("[Static Tokio Async Fn] Error at {}: {}", tm, err);
//! // })
//! // }
//! // #[cfg(feature = "notify-tokio")]
//! // add_tokio_async_err_handler!(my_static_tokio_handler);
//! ```
//!
//! After registering handlers using either functions or macros, ensure you call
//! `fix_err_handlers()` or allow the first error instantiation to implicitly
//! fix the handlers.
//!
//! ### Notification of Err instantiations
//!
//! This crate optionally provides a feature to notify pre-registered error handlers when an `Err`
//! is instantiated.
//! Multiple error handlers can be registered, and you can choose to receive notifications either
//! synchronously or asynchronously.
//! To register error handlers that receive notifications synchronously, use the
//! `add_sync_err_handler` function.
//!
//! For asynchronous notifications, there are two approaches: one for general use and another
//! specifically for applications using the Tokio runtime.
//!
//! For general-purpose asynchronous notifications, use the `add_async_err_handler` function.
//! This function is available when the `notify` feature is enabled.
//!
//! For applications using the Tokio runtime, the `add_tokio_async_err_handler` function should
//! be used. This function is available when the `notify-tokio` feature is enabled and
//! ensures that the asynchronous error handling is integrated with the Tokio runtime.
//!
//! Error notifications will not occur until the `fix_err_handlers` function is called.
//! This function locks the current set of error handlers, preventing further additions and
//! enabling notification processing.
//!
//! ```rust
//! #[cfg(feature = "notify")]
//! errs::add_sync_err_handler(|err, tm| {
//! println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
//! });
//!
//! #[cfg(feature = "notify")]
//! errs::add_async_err_handler(|err, tm| {
//! println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
//! });
//!
//! #[cfg(feature = "notify-tokio")]
//! errs::add_tokio_async_err_handler(async |err, tm| {
//! println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
//! });
//! // When rust version is less than 1.85.0.
//! //errs::add_tokio_async_err_handler(|err, tm| Box::pin(async move {
//! // println!("{}:{}:{} - {}", tm, err.file(), err.line(), err);
//! //}));
//!
//! #[cfg(any(feature = "notify", feature = "notify-tokio"))]
//! errs::fix_err_handlers();
//! ```
pub use ;
pub use ;
pub use ;
use ;
use atomic;
/// Struct that represents an error with a reason.
///
/// This struct encapsulates the reason for the error, which can be any data type.
/// Typically, the reason is an enum variant, which makes it easy to uniquely identify
/// the error kind and location in the source code.
/// In addition, since an enum variant can store additional information as their fields,
/// it is possible to provide more detailed information about the error.
///
/// The reason for the error can be distinguished with match statements, and type
/// casting, so it is easy to handle the error in a type-safe manner.
///
/// This struct also contains an optional cause error, which is the error caused the
/// current error. This is useful for chaining errors.
///
/// This struct is implements the `std::errors::Error` trait, so it can be used as an
/// common error type in Rust programs.
// When a struct contains a raw pointer as a field, the compiler cannot guarantee the safety of
// the data the pointer points to. Therefore, the Send and Sync traits are not implemented
// automatically, which means the struct cannot be safely moved or shared across threads.
//
// However, if it is verified that the data pointed to is Send and Sync, they can use an
// unsafe block to manually implement these traits.
//
// This SendSyncNonNull struct solves this issue by using a generic parameter T with a
// Send + Sync trait bound. This ensures at compile time that the internal pointer will always
// point to data that is thread-safe. As a result, it is safe to implement Send and Sync using
// unsafe on this struct itself. By including SendSyncNonNull as a field in another struct,
// that outer struct can also be made thread-safe.
/// A specialized [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html) type
/// for `errs` crate, where the error type is [`Err`].
///
/// This type is broadly used across the `errs` crate for any operation that may produce an error.
/// Its primary purpose is to avoid repeatedly writing out [`Err`] directly, making code
/// more concise.
///
/// # Examples
///
/// A convenience function that bubbles an `errs::Result` to its caller:
///
/// ```
/// use errs::{Err, Result};
///
/// #[derive(Debug)]
/// enum Reasons {
/// NotFound,
/// PermissionDenied,
/// }
///
/// fn might_fail(s: &str) -> Result<String> {
/// if s == "fail" {
/// Err(Err::new(Reasons::NotFound))
/// } else {
/// Ok(s.to_string())
/// }
/// }
///
/// fn call_might_fail() -> Result<String> {
/// let s = might_fail("test")?;
/// Ok(s)
/// }
/// ```
pub type Result<T> = Result;