resext 1.3.1

A simple, lightweight error handling crate for Rust
Documentation
# resext

**Main crate providing error handling with context chains**

This is the primary interface for ResExt. It re-exports the proc-macro as well as other helpers provided by ResExt.

---

## Installation

```toml
[dependencies]
resext = "1.0.0"
```

---

## Quick Example

```rust
use resext::resext;
use resext::ctx;

#[resext]
enum FileError {
    Io(std::io::Error),
    Parse(serde_json::Error),
}

fn load_data(path: &str) -> Res<Data> {
    let content = std::fs::read_to_string(path)
        .context(ctx!("Failed to read file: {}", path))?;
    
    let data = serde_json::from_str(&content)
        .context(ctx!("Failed to parse file: {}", path))?;
    
    Ok(data)
}
```

---

## Proc Macro

The proc macro provides clean syntax with full customization:

```rust
#[resext(
    prefix = "ERROR: ",
    suffix = "\n",
    msg_prefix = "  at: ",
    msg_suffix = "",
    delimiter = "\n",
    source_prefix = "Caused by: ",
    include_variant = true,
    alias = MyResult,
    alloc = true
)]
enum MyError {
    Network(reqwest::Error),
    Database { error: sqlx::Error },
}
```

### Attribute Options

- `prefix` - String prepended to entire error message
- `suffix` - String appended to entire error message
- `msg_prefix` - String prepended to each context message
- `msg_suffix` - String appended to each context message
- `delimiter` - Separator between context messages (default: "\n - ") 
- `source_prefix` - String prepended to source error (default: "Error: ")
- `include_variant` - Include variant name in Display output (default: false)
- `alias` - Custom type alias name which is used for getting the names for other items generated by the proc-macro (default: `Res`)
- `buf_size` - Size for the context message byte buffer (default: 64)
- `alloc` Enable heap-spilling if context exceeds `buf_size`

---

## `.context()` Method

Add static context to an error.

Accepts `&str` or `ctx!()` macro which outputs a lazily evaluated closure with usage similar to old `format_args!()` API

### Example

```rust
std::fs::read("file.txt")
    .context("Failed to read file")?;
```

---

## Error Display Format

Errors are displayed with context chains:

```
Failed to load application
 - Failed to read config file
 - Failed to open file
Error: No such file or directory
```

With `include_variant = true`:

```
Failed to load application
 - Failed to read config file
Error: Io: No such file or directory
```

---

## Examples

### Basic Error Handling

```rust
use resext::resext;
use resext::ctx;

#[resext]
enum ConfigError {
    Io(std::io::Error),
    Parse(toml::de::Error),
}

fn load_config(path: &str) -> Res<Config> {
    let content = std::fs::read_to_string(path)
        .context("Failed to read config")?;
    
    toml::from_str(&content)
        .context(ctx!("Failed to parse {}", path))
}
```

### Multiple Error Types

```rust
use resext::resext;

#[resext(alias = ApiResult)]
enum ApiError {
    Network(reqwest::Error),
    Database(sqlx::Error),
    Json(serde_json::Error),
}

async fn fetch_user(id: u64) -> ApiResult<User> {
    let response = reqwest::get(format!("/users/{}", id))
        .await
        .context("Failed to fetch user")?;
    
    let user = response.json()
        .await
        .context("Failed to parse user data")?;
    
    Ok(user)
}
```

### Named Fields

```rust
use resext::resext;

#[resext]
enum DatabaseError {
    Connection { error: sqlx::Error },
    Query { error: sqlx::Error },
}
```

---

## Contributing

See [CONTRIBUTING.md](../CONTRIBUTING.md) for guidelines.

---

## License

MIT - See [LICENSE](../LICENSE) for details.