# geez
**G**lobal **E**rror **E**mbedding **Z**ero-cost.
Typed error enums with attributes that look like `thiserror`, implemented as a plain `macro_rules!` macro. No proc-macros, no dependencies.
## Add it
```toml
[dependencies]
geez = "0.1"
```
## Use it
```rust
use geez::geez;
geez! {
pub enum AppError {
#[from]
Io(std::io::Error),
#[transparent]
Other(OtherError),
#[source]
Wrapped(std::io::Error),
#[error("bad status {0}: {1}")]
Status(u16, String),
#[error("parse failed: {0}")]
Parse(String),
Timeout => "request timed out",
NotFound,
}
}
fn load() -> Result<()> {
std::fs::read_to_string("config.toml")?;
Ok(())
}
```
That also defines `type Result<T> = std::result::Result<T, AppError>` with the same visibility as the enum.
## Attributes
| `#[from]` | `From<T>` + `Error::source` (one field) |
| `#[transparent]` | `From<T>`, Display and source forward to the inner error (one field) |
| `#[source]` | `Error::source` only — no `From` (one field) |
| `#[error("…")]` | Custom Display. Use `{0}`, `{1}`, … for fields |
| `=> "…"` | Same as `#[error("…")]`, handy for unit variants |
| unit, no message | Display is the variant name (`NotFound`) |
| one field, no message | Display is `"{}"` of the field |
`#[from]`, `#[transparent]`, and `#[source]` are mutually exclusive. Multi-field variants need an `#[error("…")]` (or `=>`).
Tuple variants support up to 8 fields.
## vs thiserror / anyhow
**thiserror** is a proc-macro with a bigger feature set (struct variants, field-level `#[source]`, more format sugar). Reach for it when you need that, or when you already depend on it.
**anyhow** is one opaque error type plus context helpers. Great for binaries and apps. Not what you want for a library’s public error enum.
**geez** sits in the thiserror lane: typed enums for libraries, familiar attributes, zero deps, declarative macro only. Use it when you want a small error enum without pulling in `syn`.
## License
MIT OR Apache-2.0