neuer_error/
lib.rs

1//! The error that can be whatever you want (it is Mr. Neuer). In every case (hopefully). NO AI
2//! SLOP!
3//!
4//! An error handling library designed to be:
5//!
6//! - Useful in both libraries and applications, containing human and machine information.
7//! - Ergonomic, low-boilerplate and comfortable, while still adhering best-practices and providing
8//!   all necessary infos.
9//! - Flexible in interfacing with other error handling libraries.
10//!
11//! ## Features/Highlights
12//!
13//! - Most importantly: error messages, that are helpful for debugging. By default it uses source
14//!   locations instead of backtraces, which is often easier to follow, more efficient and works
15//!   without debug info.
16//! - Discoverable, typed context getters without generic soup, type conversions and conflicts.
17//! - Works with std and no-std, but requires a global allocator.
18//! - Compatible with non-Send/Sync environments, but also with Send/Sync environments ([per feature
19//!   flag](#feature-flags)).
20//! - Out of the box source error chaining.
21//!
22//! ## Why a new (German: neuer) error library?
23//!
24//! Long story, you can [view it here](https://github.com/FlixCoder/neuer-error/blob/main/why-another-lib.md).
25//!
26//! TLDR: I wasn't satisfied with my previous approach and existing libraries I know. And I was
27//! inspired by a blog post to experiment myself with error handling design.
28//!
29//! ## Usage
30//!
31//! 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).
32//! Nevertheless, here is a quick demo:
33//!
34//! ```rust
35//! # use neuer_error::{traits::*, CtxError, Result, provided_attachments};
36//! // In library/module:
37//! #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
38//! pub enum Retryable { No, Yes }
39//!
40//! // Provide discoverable, typed information for library users.
41//! provided_attachments!(
42//!   retryable(single: Retryable) -> bool {
43//!     |retryable| matches!(retryable, Some(Retryable::Yes))
44//!   };
45//! );
46//!
47//! fn do_something_internal() -> Result<()> {
48//!   Err(CtxError::new("Error occurred internally")
49//!     .attach(Retryable::No))
50//! }
51//!
52//! pub fn do_something() -> Result<()> {
53//!   do_something_internal().context("Operation failed")
54//! }
55//!
56//! // In consumer/application:
57//! fn main() {
58//!   match do_something() {
59//!     Ok(()) => {}
60//!     Err(err) if err.retryable() => {
61//!       eprintln!("Retryable error");
62//!     }
63//!     Err(_) => {
64//!       eprintln!("Non-retryable error");
65//!     }
66//!   }
67//! }
68//! ```
69//!
70//! Run `cargo add neuer-error` to add the library to your project.
71//!
72//! ## Feature Flags
73//!
74//! **default** -> std, send, sync: Default selected features. Deactivate with
75//! `default-features=false`.
76//!
77//! **std** (default): Enables use of `std`. Provides interaction with `ExitCode` termination.
78//!
79//! **send** (default): Requires all contained types to be `Send`, so that [`CtxError`] is also
80//! `Send`.
81//!
82//! **sync** (default) -> send: Requires all contained types to be `Sync`, so that [`CtxError`] is
83//! also `Sync`.
84#![cfg_attr(not(feature = "std"), no_std)]
85#![warn(clippy::std_instead_of_core, clippy::std_instead_of_alloc, clippy::alloc_instead_of_core)]
86
87extern crate alloc;
88
89mod error;
90mod features;
91mod macros;
92mod results;
93
94pub use self::{
95	error::{CtxError, CtxErrorImpl},
96	results::{ConvertOption, ConvertResult, CtxResultExt, ResultExt},
97};
98
99pub mod traits {
100	//! All traits that need to be in scope for	comfortable usage.
101	pub use crate::{ConvertOption as _, ConvertResult as _, CtxResultExt as _, ResultExt as _};
102}
103
104/// `Result` type alias using the crate's [`CtxError`] type.
105pub type Result<T, E = CtxError> = ::core::result::Result<T, E>;
106
107/// Create a `Result::Ok` value with [`CtxError`] as given error type.
108#[inline(always)]
109#[expect(non_snake_case, reason = "Mimics Result::Ok")]
110pub const fn Ok<T>(value: T) -> Result<T> {
111	Result::Ok(value)
112}
113
114#[cfg(test)]
115mod tests;