| Crates.io | luhtwin |
| lib.rs | luhtwin |
| version | 0.1.4 |
| created_at | 2025-11-09 23:40:46.307944+00 |
| updated_at | 2025-12-06 12:00:19.052822+00 |
| description | A beta horrible Rust error handling library with AnyError and context macros |
| homepage | |
| repository | https://github.com/calizoots/luhtwin |
| max_upload_size | |
| id | 1924575 |
| size | 120,315 |
Error Handling for Rust
luhtwin provides an ergonomic error handling system that emphasizes context accumulation, structured diagnostics, and flexible formatting. Built around the AnyError type, it allows you to wrap any error with rich metadata and progressively add context as errors bubble up through your application.
AnyError — The main error container that wraps any Error type with context chainsLuhTwin<T> — Type alias for Result<T, AnyError>, the primary result typeErrorContext — Structured metadata including messages, file/line info, and custom argumentsWrap — Wrapping existing Results into LuhTwinTwin — Transforming existing Results into LuhTwinEncase — Encase existing LuhTwins in another layer of contextAdd luhtwin to your Cargo.toml:
[dependencies]
luhtwin = "0.1.4"
use luhtwin::{LuhTwin, Twin, Wrap, Encase, at};
use std::fs;
fn read_config_file(path: &str) -> LuhTwin<String> {
fs::read_to_string(path)
.wrap(|| format!("failed to read config from {}", path))
}
fn parse_config(content: String) -> LuhTwin<Config> {
serde_json::from_str(&content)
.twin()
.encase(|| "failed to parse config as JSON")
}
fn load_config() -> LuhTwin<Config> {
let content = read_config_file("config.json")?;
parse_config(content)
.encase(|| "config loading failed")
}
fn main() -> LuhTwin<()> {
let config = load_config()?;
println!("Config loaded successfully!");
Ok(())
}
When an error occurs, luhtwin provides detailed, layered context:
LUHTWIN_FULL=1 to see full errors <3
1: failed to read config from config.json: No such file or directory
2: failed to parse config as JSON
3: config loading failed
source: No such file or directory (os error 2)
backtrace:
disabled backtrace
With LUHTWIN_FULL=1, you get full context including file/line info and attached arguments.
.twin()use std::fs::File;
fn open_file() -> LuhTwin<File> {
File::open("data.txt").twin()
}
.wrap()fn read_user_data(id: u32) -> LuhTwin<UserData> {
read_from_db(id).wrap(|| format!("failed to load user {}", id))
}
.encase()fn initialize() -> LuhTwin<()> {
load_config()
.encase(|| "initialization failed")?;
connect_db()
.encase(|| "initialization failed")?;
Ok(())
}
at! macro for rich contextfn validate_input(input: &str) -> LuhTwin<()> {
if input.is_empty() {
return Err(at!("input validation failed")
.attach("input", input)
.attach("expected", "non-empty string")
.into());
}
Ok(())
}
LUHTWIN_FULL=1 - Show full error details with all attached argumentsRUST_BACKTRACE=1 - Enable backtrace capture (standard Rust behavior)For full documentation, see docs.rs/luhtwin.
made with love - s.c