luhtwin

Crates.ioluhtwin
lib.rsluhtwin
version0.1.4
created_at2025-11-09 23:40:46.307944+00
updated_at2025-12-06 12:00:19.052822+00
descriptionA beta horrible Rust error handling library with AnyError and context macros
homepage
repositoryhttps://github.com/calizoots/luhtwin
max_upload_size
id1924575
size120,315
s (calizoots)

documentation

README

luhtwin

github crates.io docs.rs

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.

Core Ideas

  • AnyError — The main error container that wraps any Error type with context chains
  • LuhTwin<T> — Type alias for Result<T, AnyError>, the primary result type
  • ErrorContext — Structured metadata including messages, file/line info, and custom arguments
  • Wrap — Wrapping existing Results into LuhTwin
  • Twin — Transforming existing Results into LuhTwin
  • Encase — Encase existing LuhTwins in another layer of context

Quick Start

Add luhtwin to your Cargo.toml:

[dependencies]
luhtwin = "0.1.4"

Example

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(())
}

Error Output

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.

Common Patterns

Converting foreign errors with .twin()

use std::fs::File;

fn open_file() -> LuhTwin<File> {
    File::open("data.txt").twin()
}

Wrapping errors with context using .wrap()

fn read_user_data(id: u32) -> LuhTwin<UserData> {
    read_from_db(id).wrap(|| format!("failed to load user {}", id))
}

Adding layers with .encase()

fn initialize() -> LuhTwin<()> {
    load_config()
        .encase(|| "initialization failed")?;
    connect_db()
        .encase(|| "initialization failed")?;
    Ok(())
}

Using the at! macro for rich context

fn 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(())
}

Environment Variables

  • LUHTWIN_FULL=1 - Show full error details with all attached arguments
  • RUST_BACKTRACE=1 - Enable backtrace capture (standard Rust behavior)

Documentation

For full documentation, see docs.rs/luhtwin.


made with love - s.c

Commit count: 0

cargo fmt