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
//! The error that can be whatever you want (it is Mr. Neuer). In every case (hopefully). NO AI
//! SLOP!
//!
//! An error handling library designed to be:
//!
//! - Useful in both libraries and applications, containing human and machine information.
//! - Ergonomic, low-boilerplate and comfortable, while still adhering best-practices and providing
//! all necessary infos.
//! - Flexible in interfacing with other error handling libraries.
//!
//! ## Features/Highlights
//!
//! - Most importantly: error messages, that are helpful for debugging. By default it uses source
//! locations instead of backtraces, which is often easier to follow, more efficient and works
//! without debug info.
//! - Discoverable, typed context getters without generic soup, type conversions and conflicts.
//! - Optional macro rule to force yourself at compile-time to add additional context in functions.
//! - Compatible with non-Send/Sync environments, but also with Send/Sync environments ([per feature
//! flag](#feature-flags)).
//! - Works with std and no-std, but requires a global allocator.
//! - Out of the box source error chaining.
//! - No dependencies by default. Optional features may lead to some dependencies.
//! - No `unsafe` used (yet?).
//!
//! ## Why a new (German: neuer) error library?
//!
//! Long story, you can [view it here](https://github.com/FlixCoder/neuer-error/blob/main/why-another-lib.md).
//!
//! TLDR: I wasn't satisfied with my previous approach and existing libraries I know. And I was
//! inspired by a blog post to experiment myself with error handling design.
//!
//! ## Usage
//!
//! The best way to see how to use it for your use-case is to check out the [examples](https://github.com/FlixCoder/neuer-error/tree/main/examples).
//! Nevertheless, here is a quick demo:
//!
//! ```rust
//! # use neuer_error::{traits::*, NeuErr, Result, provided_attachments, require_context};
//! // In library/module:
//! #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
//! pub enum Retryable { No, Yes }
//!
//! // Provide discoverable, typed information for library users.
//! provided_attachments!(
//! retryable(single: Retryable) -> bool {
//! |retryable| matches!(retryable, Some(Retryable::Yes))
//! };
//! );
//!
//! fn do_something_internal() -> Result<()> {
//! Err(NeuErr::new("Error occurred internally")
//! .attach(Retryable::No)
//! .into())
//! }
//!
//! #[macro_rules_attribute::apply(require_context)]
//! pub fn do_something() -> Result<()> {
//! // There would be a compile-time error if no context was given.
//! do_something_internal().context("Operation failed")?;
//! Ok(())
//! }
//!
//! // In consumer/application:
//! fn main() {
//! match do_something() {
//! Ok(()) => {}
//! Err(err) if err.retryable() => {
//! eprintln!("Retryable error");
//! }
//! Err(_) => {
//! eprintln!("Non-retryable error");
//! }
//! }
//! }
//! ```
//!
//! Run `cargo add neuer-error` to add the library to your project.
//!
//! ## Error Formatting
//!
//! Error formatting is targeted towards developers. If you need to show errors to users, it is
//! recommended to use special attachments for that ([see example](examples/non-dev-user.rs)).
//!
//! The error will be formatted in a "pretty" multi-line format (`{err}` or `{err:?}`):
//!
//! ```text
//! Failed compiling code
//! |- at examples/tool-cli.rs:33:23
//! |
//! Preprocessor failed
//! |- at examples/tool-cli.rs:22:25
//! |
//! Binary gcc not found
//! |- at examples/tool-cli.rs:17:9
//! ```
//!
//! Single-line formatting can be achieved via the alternate formatting mode (`{err:#}`):
//!
//! ```text
//! Failed compiling code (at examples/tool-cli.rs:33:23); Preprocessor failed (at examples/tool-cli.rs:22:25); Binary gcc not found (at examples/tool-cli.rs:17:9)
//! ```
//!
//! The error can be formatted using Rust's default debug structure with alternate debug mode
//! (`{err:#?}`).
//!
//! ## Comparisons
//!
//! ### Anyhow / Eyre
//!
//! - `NeuErr` provides a meechanism to discover and retrieve multiple items of typed context
//! information, while `anyhow` can `downcast` to its source error types only.
//! - `NeuErr` provides a helper to ensure you don't forget to add context to your errors.
//! - `NeuErr` captures source locations instead of backtraces by default, which is more efficient
//! and works without debug info. I personally also find it easier to read.
//!
//! ### Thiserror / Snafu
//!
//! - `NeuErr` is a single error type for all errors, so no need for boilerplate, better ergonomics,
//! but less type safety and flexibility.
//! - `NeuErr` captures source location automatically, which `thiserror` does not and `snafu` does
//! only when you add the location field to every error variant.
//! - `NeuErr` prints the full (source) error chain already.
//! - `NeuErr` does not have procedural macros.
//!
//! ## Feature Flags
//!
//! **default** -> std, send, sync: Default selected features. Deactivate with
//! `default-features=false`.
//!
//! **std** (default): Enables use of `std`. Provides interaction with `ExitCode` termination.
//!
//! **send** (default): Requires all contained types to be `Send`, so that [`NeuErr`] is also
//! `Send`.
//!
//! **sync** (default) -> send: Requires all contained types to be `Sync`, so that [`NeuErr`] is
//! also `Sync`.
//!
//! **colors**: Activates colored error formatting via `yansi` (added dependency). When std it
//! enabled, it also enables `yansi`'s automatic detection whether to use or not use colors. See
//! `yansi`'s documentation on details.
extern crate alloc;
pub use ;
/// `Result` type alias using the crate's [`NeuErr`] type.
pub type Result<T, E = NeuErr> = Result;
/// Create a `Result::Ok` value with [`NeuErr`] as given error type.
pub const