| Crates.io | fack |
| lib.rs | fack |
| version | 0.1.2 |
| created_at | 2025-11-05 17:18:28.277647+00 |
| updated_at | 2025-11-05 17:18:28.277647+00 |
| description | Declarative error handling library with no_std support and composable code generation |
| homepage | https://github.com/wafkse/fack |
| repository | https://github.com/wafkse/fack |
| max_upload_size | |
| id | 1918282 |
| size | 17,501 |
Error handling derive macro for Rust. no_std compatible, doesn't allocate.
use fack::prelude::*;
#[derive(Error, Debug)]
#[error("file not found: {path}")]
struct FileError {
path: String,
}
[dependencies]
fack = "0.1.0"
no_std environments - uses ::core by default, zero heap allocations at runtime#[error(inline(...))] - matters for hot paths and code sizefack-codegen is a standalone library - use it in your own macros or build scriptsIf you're writing embedded code or care about allocation-free error handling, this might be useful.
Basic struct:
use fack::prelude::*;
#[derive(Error, Debug)]
#[error("database error: {msg}")]
struct DbError {
msg: String,
}
Error chaining:
use fack::prelude::*;
#[derive(Error, Debug)]
#[error("request failed")]
#[error(source(io))]
struct RequestError {
io: std::io::Error,
url: String,
}
Enums with variants:
use fack::prelude::*;
#[derive(Error, Debug)]
enum ParseError {
#[error("invalid syntax at line {line}")]
Syntax { line: usize },
#[error("unexpected end of file")]
Eof,
#[error(transparent(0))]
Io(std::io::Error),
}
Auto-conversion with from:
use fack::prelude::*;
#[derive(Error, Debug)]
enum AppError {
#[error("io error")]
#[error(from)]
Io(std::io::Error),
#[error("parse error")]
#[error(from)]
Parse(std::num::ParseIntError),
}
// Now you can use ? with these error types
fn example() -> Result<(), AppError> {
let _file = std::fs::read("file.txt")?; // converts io::Error
let _num: i32 = "123".parse()?; // converts ParseIntError
Ok(())
}
Format strings - #[error("message")]
Use {field} for named fields, {_0} for tuple fields. Standard format specifiers work.
#[derive(Error, Debug)]
#[error("value {value} out of range {min}..{max}")]
struct RangeError { value: i32, min: i32, max: i32 }
#[derive(Error, Debug)]
#[error("invalid input: {_0:?}")]
struct InputError(String);
Source - #[error(source(field))]
Mark which field contains the underlying error. Enables error chain traversal.
#[derive(Error, Debug)]
#[error("operation failed")]
#[error(source(cause))]
struct OpError {
cause: std::io::Error,
}
Transparent - #[error(transparent(field))]
Forward display and source to an inner error. Useful for wrapper types.
#[derive(Error, Debug)]
#[error(transparent(0))]
struct Wrapper(std::io::Error);
From - #[error(from)]
Generate From<T> impl for the error type. Requires exactly one field.
#[derive(Error, Debug)]
#[error("wrapped io error")]
#[error(from)]
struct IoWrapper(std::io::Error);
Inline - #[error(inline(strategy))]
Control inlining of generated methods. Options: neutral (default), always, never.
#[derive(Error, Debug)]
#[error(inline(always))] // force inline for hot paths
#[error("fast error")]
struct HotPathError { code: u32 }
Import - #[error(import(path))]
Override the default ::core import. Use ::std if you need std-specific features.
#[derive(Error, Debug)]
#[error(import(::std))]
#[error("std error")]
struct StdError { msg: String }
Full docs at docs.rs/fack.
This repo has four crates:
fack - Main crate, re-exports everythingfack-core - Error trait definitionfack-macro - Procedural macro implementationfack-codegen - Code generation engineThe fack-codegen crate is deliberately not a proc-macro crate. You can depend on it in regular code to build custom error macros or generate errors at build time.
GPL-3.0
Copyright (C) 2025 W. Frakchi
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See LICENSE.md for the full text.