error_rail/simple.rs
1//! # Simple API - Beginner-Friendly Error Handling
2//!
3//! This module provides the **minimal surface area** for getting started with error-rail.
4//! If you're new to the library, start here.
5//!
6//! # Golden Path (3 Rules)
7//!
8//! 1. **Return `BoxedResult` at function boundaries**
9//! 2. **Add `.ctx()` only after I/O or external calls**
10//! 3. **Use `Validation` when multiple errors can occur** (see [`crate::validation`])
11//!
12//! # Quick Start
13//!
14//! ```rust
15//! use error_rail::simple::*;
16//!
17//! fn read_config() -> BoxedResult<String, std::io::Error> {
18//! std::fs::read_to_string("config.toml")
19//! .ctx("loading configuration")
20//! }
21//!
22//! fn main() {
23//! if let Err(e) = read_config() {
24//! eprintln!("{}", e.error_chain());
25//! // loading configuration -> No such file or directory (os error 2)
26//! }
27//! }
28//! ```
29//!
30//! # What's Included
31//!
32//! | Item | Purpose |
33//! |------|---------|
34//! | [`BoxedResult`] | Return type for functions (8-byte stack footprint) |
35//! | [`rail!`] | Wrap any `Result` and box the error |
36//! | [`.ctx()`](ResultExt::ctx) | Add context to errors |
37//! | [`.error_chain()`](ComposableError::error_chain) | Format error with full context chain |
38//!
39//! # What's NOT Included (Intentionally)
40//!
41//! These are available in [`crate::prelude`] or specialized modules:
42//!
43//! - `Validation` - For accumulating multiple errors (see [`crate::validation`])
44//! - `Retry` / `TransientError` - For retry logic (see [`crate::intermediate`])
45//! - `Fingerprint` - For error deduplication (see [`crate::intermediate`])
46//! - `AsyncErrorPipeline` - For async chains (see [`crate::prelude_async`])
47//!
48//! # Anti-Patterns
49//!
50//! ```rust,compile_fail
51//! # use error_rail::simple::*;
52//! // ❌ DON'T: Chain .ctx() multiple times in one expression
53//! fn bad() -> BoxedResult<String, std::io::Error> {
54//! std::fs::read_to_string("config.toml")
55//! .ctx("step 1")
56//! .ctx("step 2") // Redundant - adds noise, not value
57//! }
58//! ```
59//!
60//! ```rust
61//! # use error_rail::simple::*;
62//! // ✅ DO: One .ctx() per I/O boundary
63//! fn good() -> BoxedResult<String, std::io::Error> {
64//! std::fs::read_to_string("config.toml")
65//! .ctx("loading configuration")
66//! }
67//! ```
68//!
69//! # When NOT to Use error-rail
70//!
71//! - Simple scripts where you just print errors and exit
72//! - Projects where the team has little Rust experience
73//! - When `anyhow` or `eyre` already meets your needs
74//!
75//! # Relationship to std::error
76//!
77//! > **std::error defines error types. error-rail defines how errors flow.**
78//!
79//! error-rail wraps your existing error types and adds context propagation,
80//! without requiring you to change your error definitions.
81
82// Minimal macro - just rail! for beginners
83pub use crate::rail;
84
85// Core type for method access (error_chain, etc.)
86pub use crate::types::ComposableError;
87
88// Essential traits for .ctx() and .ctx_boxed() methods
89pub use crate::traits::{BoxedResultExt, ResultExt};
90
91// The recommended return type
92pub use crate::prelude::BoxedResult;