Async extensions for Rust’s [Result<T, E>
].
This crate provides asynchronous counterparts of the standard Result
methods (map
, and_then
, map_err
, inspect
), allowing you to use async closures seamlessly.
The standard library’s Result
methods (map
, and_then
, etc.) only work with synchronous closures.
When writing async code, you often need to .await
inside these transformations. This crate fills that gap.
Instead of:
let res: Result<i32, &str> = Ok(5);
let mapped = match res {
Ok(v) => Ok(async { v * 2 }.await),
Err(e) => Err(e),
};
You can just write:
use async_result_ext::AsyncResultExt;
let res: Result<i32, &str> = Ok(5);
let mapped = res.async_map(|v| async move { v * 2 }).await;
assert_eq!(mapped, Ok(10));
Add this to your Cargo.toml
:
[dependencies]
async-result-ext = "0.1.0"
use async_result_ext::AsyncResultExt;
#[tokio::main]
async fn main() {
let r: Result<i32, &str> = Ok(2);
// async_map: transform Ok values asynchronously
let doubled = r.async_map(|v| async move { v * 2 }).await;
assert_eq!(doubled, Ok(4));
// async_and_then: chain async computations returning Result
let chained = doubled.async_and_then(|v| async move { Ok(v + 3) }).await;
assert_eq!(chained, Ok(7));
// async_map_or: provide a default for Err cases
let res = Err::<i32, &str>("fail");
let fallback = res.async_map_or(100, |v| async move { v * 10 }).await;
assert_eq!(fallback, 100);
// async_map_err: transform errors asynchronously
let err: Result<i32, &str> = Err("oops");
let mapped_err = err.async_map_err(|e| async move { e.len() }).await;
assert_eq!(mapped_err, Err(4));
// async_inspect & async_inspect_err: peek into values without changing them
let ok: Result<i32, &str> = Ok(42);
ok.async_inspect(|v| async move {
println!("Got value: {v}");
}).await;
let err: Result<i32, &str> = Err("fail");
err.async_inspect_err(|e| async move {
eprintln!("Error: {e}");
}).await;
// async_is_ok_and: check condition asynchronously on Ok values
let r: Result<i32, &str> = Ok(10);
let is_even = r.async_is_ok_and(|v| async move { v % 2 == 0 }).await;
assert!(is_even);
// async_is_err_and: check condition asynchronously on Err values
let r: Result<i32, &str> = Err("boom!");
let too_long = r.async_is_err_and(|e| async move { e.len() > 3 }).await;
assert!(too_long);
}
async_map
– async version of [Result::map
]async_and_then
– async version of [Result::and_then
]async_map_or
– async version of [Result::map_or
]async_map_or_else
– async version of [Result::map_or_else
]async_map_err
– async version of [Result::map_err
]async_inspect
– async version of [Result::inspect
]async_inspect_err
– async version of [Result::inspect_err
]async_is_ok_and
- async version of [Result::is_ok_and
]async_is_err_and
- async version of [Result::is_err_and
]
- Minimal and lightweight
- No dependencies (except your async runtime, e.g. Tokio or async-std)
- Familiar API – mirrors the standard library’s
Result
methods
MIT License. See LICENSE for details.