Skip to main content

suzunari_error/
lib.rs

1//! A highly traceable and noise-free error handling library for Rust.
2//!
3//! Built on [SNAFU](https://docs.rs/snafu), this crate propagates error locations
4//! as error contexts and formats error chains as stack-trace-like reports.
5//! `#![no_std]` compatible with 3 feature tiers: core-only / `alloc` / `std`.
6//!
7//! # Quick Start
8//!
9//! Use [`#[suzunari_error]`](macro@suzunari_error) to define error types — it combines
10//! location injection, `Snafu` derive, and `StackError` derive in one attribute:
11//!
12//! ```
13//! use suzunari_error::*;
14//!
15//! #[suzunari_error]
16//! #[suzu(display("operation failed"))]
17//! struct AppError {
18//!     source: std::io::Error,
19//! }
20//! ```
21//!
22//! # Key Types
23//!
24//! - [`Location`] — Type alias for `&'static core::panic::Location<'static>`; captures call-site file/line/column
25//! - [`StackError`] — Extends `Error` with `location()`, `type_name()`, `stack_source()`, and `depth()`
26//! - [`StackReport`] — Formats a `StackError` chain for display with location info
27//! - [`BoxedStackError`] — Type-erased `StackError` wrapper (requires `alloc`)
28//! - [`DisplayError`] — Adapter for `Debug + Display` types that don't implement `Error`
29//!
30//! # Feature Flags
31//!
32//! | Feature | Default | Provides |
33//! |---------|---------|----------|
34//! | `std`   | Yes     | `alloc` + [`StackReport`]'s [`Termination`](std::process::Termination) impl + [`#[report]`](macro@report) macro |
35//! | `alloc` | via `std` | [`BoxedStackError`] + `From<T> for BoxedStackError` generation |
36//! | _(none)_ | —      | Core-only: [`Location`], [`StackError`], [`StackReport`] (formatting only), [`DisplayError`] |
37//!
38//! # `#[suzu(...)]` Attribute
39//!
40//! Use `#[suzu(...)]` for all attributes under [`#[suzunari_error]`](macro@suzunari_error).
41//! It is a superset of `#[snafu(...)]` — standard snafu keywords (`display`, `source`,
42//! `visibility`, etc.) pass through as-is, plus suzunari extensions are available.
43//! `#[snafu(...)]` also works, but `#[suzu(...)]` is preferred for consistency.
44//!
45//! Suzunari extensions:
46//!
47//! - **`from`** (field-level) — wraps a field type in [`DisplayError<T>`] and generates
48//!   a `source(from(...))` conversion that automatically preserves the `Error::source()`
49//!   chain when the wrapped type implements `Error`
50//! - **`location`** (field-level) — marks a field as the location field with a custom name;
51//!   converts to `#[stack(location)]` + `#[snafu(implicit)]`
52//!
53//! # Known Limitations
54//!
55//! - **Location type detection** uses the last path segment name (`Location`), not the
56//!   full path. A user-defined `my_module::Location` type may trigger false auto-detection.
57//!   Writing the expanded type (`&'static core::panic::Location<'static>`) directly also
58//!   bypasses auto-detection. Use `#[suzu(location)]` or `#[stack(location)]` to disambiguate.
59//! - **Crate renaming** (`my_error = { package = "suzunari-error" }`) is not supported.
60//!   The generated code always references `::suzunari_error`. This matches the approach
61//!   used by snafu and thiserror.
62
63#![no_std]
64#![forbid(unsafe_code)]
65#![warn(missing_docs)]
66
67#[cfg(feature = "alloc")]
68extern crate alloc;
69
70#[cfg(feature = "std")]
71extern crate std;
72
73mod display_error;
74mod stack_error;
75mod stack_report;
76
77#[doc(hidden)]
78pub mod __private;
79
80#[cfg(feature = "alloc")]
81mod boxed_stack_error;
82
83#[cfg(feature = "alloc")]
84pub use boxed_stack_error::BoxedStackError;
85/// Type alias for `&'static core::panic::Location<'static>`.
86///
87/// Used as the location field type in error structs generated by [`#[suzunari_error]`](macro@suzunari_error).
88/// [`snafu::GenerateImplicitData`] is implemented for this type by snafu, so location fields
89/// marked with `#[snafu(implicit)]` are automatically populated via `#[track_caller]`.
90pub type Location = &'static core::panic::Location<'static>;
91
92pub use display_error::DisplayError;
93pub use stack_error::StackError;
94pub use stack_report::StackReport;
95
96// Re-export snafu so downstream crates don't need it as a direct dependency.
97// The proc-macro generates `#[snafu(crate_root(::suzunari_error::snafu))]`
98// to redirect snafu's generated paths here.
99// Note: bumping the snafu dependency version is a semver-breaking change for
100// downstream crates, because these re-exports are part of our public API.
101pub use snafu;
102// OptionExt is not used within this crate but re-exported for downstream
103// convenience: it enables `.context()` on `Option<T>` to convert None into errors.
104pub use snafu::{OptionExt, ResultExt, ensure};
105
106// Proc-macro re-exports (wildcard is the only way to re-export proc macros).
107pub use suzunari_error_macro_impl::*;