Skip to content

Commit

Permalink
doc: Update
Browse files Browse the repository at this point in the history
  • Loading branch information
mcmah309 committed Jul 20, 2024
1 parent 70a2ba7 commit 4e9d2fc
Show file tree
Hide file tree
Showing 2 changed files with 113 additions and 5 deletions.
112 changes: 110 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,10 +389,9 @@ As mentioned, any above subset can be converted into a superset with `.into()` o
Error enums and error variants can also accept doc comments and attributes like `#[derive(...)]`.
Intersecting sets can also be more easily handled with the `coerce!` macro (must have the "coerce_macro" feature enabled).

### `error_set!` Example
<details>

<summary>Base Functionality In Action</summary>
<summary>Basic Example</summary>

```rust
use error_set::error_set;
Expand Down Expand Up @@ -435,6 +434,115 @@ fn main() {
```
</details>

### Features

**coerce_macro:** Each error set will generates a `coerce!` macro to help handle coercsion between partially intersecting sets.

```rust
let val = coerce!(setx => {
Ok(val) => val,
Err(SetX::X) => {}, // handle disjointedness
{ Err(SetX) => return Err(SetY) } // terminal coercion
})?;
```

<details>

<summary>More Details</summary>

Given:
```rust
error_set! {
SetX = {
X
} || Common;
SetY = {
Y
} || Common;
Common = {
A,
B,
C,
D,
E,
F,
G,
H,
};
}
```

rather than writing:

```rust
fn setx_result_to_sety_result() -> Result<(), SetY> {
let _ok = match setx_result() {
Ok(ok) => ok,
Err(SetX::X) => {} // handle disjointedness
Err(SetX::A) => {
return Err(SetY::A);
}
Err(SetX::B) => {
return Err(SetY::B);
}
Err(SetX::C) => {
return Err(SetY::C);
}
Err(SetX::D) => {
return Err(SetY::D);
}
Err(SetX::E) => {
return Err(SetY::E);
}
Err(SetX::F) => {
return Err(SetY::F);
}
Err(SetX::G) => {
return Err(SetY::G);
}
Err(SetX::H) => {
return Err(SetY::H);
}
};
Ok(())
}
```

one can write this, which compiles to the `match` statement above:

```rust
fn setx_result_to_sety_result() -> Result<(), SetY> {
let _ok = coerce!(setx_result() => {
Ok(ok) => ok,
Err(SetX::X) => {}, // handle disjointedness
{ Err(SetX) => return Err(SetY) } // terminal coercion
});
Ok(())
}
```

The `coerce!` macro is a flat fast (no tt muncher 🦫) declarative macro created by the `error_set!` macro for the set.
`coerce!` behaves like a regular `match` statement, except it allows a terminal coercion statement between sets. e.g.

```rust
{ Err(SetX) => return Err(SetY) }
{ Err(SetX) => Err(SetY) }
{ SetX => return SetY }
{ SetX => SetY }
```

With `coerce!`, one can concisely handle specific variants of errors as they bubble up the call stack and propagate the rest.
</details>

**tracing:** Enables support for the tracing crate. Adds methods to `Result` that are applied on `Err`. Similar to anyhow's `.context(..)`.
```rust
let value = result.warn("This a warning that will be passed to tracing if `Err`")?;
```
**log:** Enables support for the log crate. Adds methods to `Result` that are applied on `Err`. Similar to anyhow's `.context(..)`.
```rust
let value = result.warn("This a warning that will be passed to tracing if `Err`")?;
```

### Why Choose `error_set` Over `thiserror` or `anyhow`

If your project doesn't require handling specific error types and you just need to propagate errors up the call stack, then `anyhow` is likely the best choice for you. It's straightforward and effective for simple error management.
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#![doc = include_str!("../README.md")]
#![cfg_attr(feature = "coerce_macro", doc = "Generates a `coerce!` macro for each error set to handle coercing between intersections.")]
#![cfg_attr(feature = "tracing", doc = "Enables tracing crate methods on `Result` that are applied on `Err` - e.g. `result.warn(...)`.")]
#![cfg_attr(feature = "log", doc = "Enables logging crate methods on `Result` that are applied on `Err` - e.g. `result.warn(...)`.")]
#![cfg_attr(feature = "coerce_macro", doc = "Each error set will generates a `coerce!` macro to help handle coercsion between partially intersecting sets.")]
#![cfg_attr(feature = "tracing", doc = "Enables support for the tracing crate. Adds methods to `Result` that are applied on `Err` - e.g. `result.warn(...)`.")]
#![cfg_attr(feature = "log", doc = "Enables support for the log crate. Adds methods to `Result` that are applied on `Err` - e.g. `result.warn(...)`.")]
#[cfg(all(feature = "tracing", feature = "log"))]
compile_error!("Features 'tracing' and 'log' cannot be enabled at the same time.");

Expand Down

0 comments on commit 4e9d2fc

Please sign in to comment.