From 4e9d2fc8f0c714dac260e070220befd4ee96bc35 Mon Sep 17 00:00:00 2001 From: mcmah309 Date: Sat, 20 Jul 2024 04:05:56 +0000 Subject: [PATCH] doc: Update --- README.md | 112 ++++++++++++++++++++++++++++++++++++++++++++++++++++- src/lib.rs | 6 +-- 2 files changed, 113 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 420935e..b4f07f3 100644 --- a/README.md +++ b/README.md @@ -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
- Base Functionality In Action + Basic Example ```rust use error_set::error_set; @@ -435,6 +434,115 @@ fn main() { ```
+### 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 + })?; +``` + +
+ +More Details + +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. +
+ +**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. diff --git a/src/lib.rs b/src/lib.rs index 033e6f3..d83c2a9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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.");