# async-ops [![CI](https://github.com/saserr/async-ops/actions/workflows/CI.yml/badge.svg)](https://github.com/saserr/async-ops/actions/workflows/CI.yml) [![codecov](https://codecov.io/gh/saserr/async-ops/branch/main/graph/badge.svg?token=2K2DABXJMS)](https://codecov.io/gh/saserr/async-ops) [![License](https://img.shields.io/badge/license-Apache--2.0_OR_MIT-blue.svg)]( https://github.com/saserr/async-ops) This crate provides a way to use [some `std::ops` traits](#supported-stdops-traits) with `Futures`. To be able to use a `std::ops` trait with a `Future`, first you need to wrap the `Future` with `Async` using `async_ops::on`. Then, as long the `Future::Output` type implements a supported `std::ops` trait, then the same `std::ops` trait will be implemented by the `Async` instance. Another option is to wrap a `Future` with `Async` using `async_ops::assignable!` to enable usage of the `Assign` variants of `std::ops` traits on the `Future`. ## Example When writing `async` code it is common to do operations that are supported through `std::ops`. For example, adding to numbers might look like this: ```rust use futures_executor::block_on; // Immediately returning a number is done for simplicity and production code // wouldn't just immediately return a value. let a = async { 40 }; let b = async { 2 }; let result = async { a.await + b.await }; assert_eq!(42, block_on(result)); ``` Actually, the above code is not optimally implemented because `a` and `b` are `await`-ed sequentially, instead of concurrently. The appropriate solution is to use `join!` to be able to concurrently `await` both values like this: ```rust use futures_executor::block_on; use futures_util::join; let a = async { 40 }; let b = async { 2 }; let result = async { let (a, b) = join!(a, b); a + b }; assert_eq!(42, block_on(result)); ``` Or, just use `async_ops::on` to do the same thing like the above example in one line: ```rust use futures_executor::block_on; let a = async { 40 }; let b = async { 2 }; let result = async { (async_ops::on(a) + b).await }; assert_eq!(42, block_on(result)); ``` Note that the `async_ops::on` example will also concurrently `await` both values. ## Supported `std::ops` traits
Add `Async` implements `Add where Rhs: Future` when the wrapped `Future::Output` type implements `Add`. The resulting type of the addition is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 40 }; let b = async { 2 }; let result = async { (async_ops::on(a) + b).await }; assert_eq!(42, block_on(result)); ```
AddAssign `Async` implements `AddAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Add>::Output>`, which in turn requires the `Future::Output` type to implement `Add`. ```rust use futures_executor::block_on; let a = async { 40 }; let b = async { 2 }; let result = async { async_ops::assignable!(a); a += b; a.await }; assert_eq!(42, block_on(result)); ```
BitAnd `Async` implements `BitAnd where Rhs: Future` when the wrapped `Future::Output` type implements `BitAnd`. The resulting type of the bitwise and is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 110 }; let b = async { 59 }; let result = async { (async_ops::on(a) & b).await }; assert_eq!(42, block_on(result)); ```
BitAndAssign `Async` implements `BitAndAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as BitAnd>::Output>`, which in turn requires the `Future::Output` type to implement `BitAnd`. ```rust use futures_executor::block_on; let a = async { 110 }; let b = async { 59 }; let result = async { async_ops::assignable!(a); a &= b; a.await }; assert_eq!(42, block_on(result)); ```
BitOr `Async` implements `BitOr where Rhs: Future` when the wrapped `Future::Output` type implements `BitOr`. The resulting type of the bitwise or is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 40 }; let b = async { 10 }; let result = async { (async_ops::on(a) | b).await }; assert_eq!(42, block_on(result)); ```
BitOrAssign `Async` implements `BitOrAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as BitOr>::Output>`, which in turn requires the `Future::Output` type to implement `BitOr`. ```rust use futures_executor::block_on; let a = async { 40 }; let b = async { 10 }; let result = async { async_ops::assignable!(a); a |= b; a.await }; assert_eq!(42, block_on(result)); ```
BitXor `Async` implements `BitXor where Rhs: Future` when the wrapped `Future::Output` type implements `BitXor`. The resulting type of the bitwise xor is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 38 }; let b = async { 12 }; let result = async { (async_ops::on(a) ^ b).await }; assert_eq!(42, block_on(result)); ```
BitXorAssign `Async` implements `BitXorAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as BitXor>::Output>`, which in turn requires the `Future::Output` type to implement `BitXor`. ```rust use futures_executor::block_on; let a = async { 38 }; let b = async { 12 }; let result = async { async_ops::assignable!(a); a ^= b; a.await }; assert_eq!(42, block_on(result)); ```
Div `Async` implements `Div where Rhs: Future` when the wrapped `Future::Output` type implements `Div`. The resulting type of the division is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 84 }; let b = async { 2 }; let result = async { (async_ops::on(a) / b).await }; assert_eq!(42, block_on(result)); ```
DivAssign `Async` implements `DivAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Div>::Output>`, which in turn requires the `Future::Output` type to implement `Div`. ```rust use futures_executor::block_on; let a = async { 84 }; let b = async { 2 }; let result = async { async_ops::assignable!(a); a /= b; a.await }; assert_eq!(42, block_on(result)); ```
Mul `Async` implements `Mul where Rhs: Future` when the wrapped `Future::Output` type implements `Mul`. The resulting type of the multiplication is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 21 }; let b = async { 2 }; let result = async { (async_ops::on(a) * b).await }; assert_eq!(42, block_on(result)); ```
MulAssign `Async` implements `MulAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Mul>::Output>`, which in turn requires the `Future::Output` type to implement `Mul`. ```rust use futures_executor::block_on; let a = async { 21 }; let b = async { 2 }; let result = async { async_ops::assignable!(a); a *= b; a.await }; assert_eq!(42, block_on(result)); ```
Neg `Async` implements `Neg` when the wrapped `Future::Output` type implements `Neg`. The resulting type of the negation is `Async::Output>>`. ```rust use futures_executor::block_on; let a = async { -42 }; let result = async { (-async_ops::on(a)).await }; assert_eq!(42, block_on(result)); ```
Not `Async` implements `Not` when the wrapped `Future::Output` type implements `Not`. The resulting type of the logical negation is `Async::Output>>`. ```rust use futures_executor::block_on; let a = async { 213_u8 }; let result = async { (!async_ops::on(a)).await }; assert_eq!(42, block_on(result)); ```
Rem `Async` implements `Rem where Rhs: Future` when the wrapped `Future::Output` type implements `Rem`. The resulting type of the reminder operation is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 42 }; let b = async { 5 }; let result = async { (async_ops::on(a) % b).await }; assert_eq!(2, block_on(result)); ```
RemAssign `Async` implements `RemAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Rem>::Output>`, which in turn requires the `Future::Output` type to implement `Rem`. ```rust use futures_executor::block_on; let a = async { 42 }; let b = async { 5 }; let result = async { async_ops::assignable!(a); a %= b; a.await }; assert_eq!(2, block_on(result)); ```
Shl `Async` implements `Shl where Rhs: Future` when the wrapped `Future::Output` type implements `Shl`. The resulting type of the left shift is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 21 }; let b = async { 1 }; let result = async { (async_ops::on(a) << b).await }; assert_eq!(42, block_on(result)); ```
ShlAssign `Async` implements `ShlAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Shl>::Output>`, which in turn requires the `Future::Output` type to implement `Shl`. ```rust use futures_executor::block_on; let a = async { 21 }; let b = async { 1 }; let result = async { async_ops::assignable!(a); a <<= b; a.await }; assert_eq!(42, block_on(result)); ```
Shr `Async` implements `Shr where Rhs: Future` when the wrapped `Future::Output` type implements `Shr`. The resulting type of the right shift is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 168 }; let b = async { 2 }; let result = async { (async_ops::on(a) >> b).await }; assert_eq!(42, block_on(result)); ```
ShrAssign `Async` implements `ShrAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Shr>::Output>`, which in turn requires the `Future::Output` type to implement `Shr`. ```rust use futures_executor::block_on; let a = async { 168 }; let b = async { 2 }; let result = async { async_ops::assignable!(a); a >>= b; a.await }; assert_eq!(42, block_on(result)); ```
Sub `Async` implements `Sub where Rhs: Future` when the wrapped `Future::Output` type implements `Sub`. The resulting type of the subtraction is `Async>::Output>>`. ```rust use futures_executor::block_on; let a = async { 44 }; let b = async { 2 }; let result = async { (async_ops::on(a) - b).await }; assert_eq!(42, block_on(result)); ```
SubAssign `Async` implements `SubAssign where Rhs: Future` when the wrapped `Future` type implements `Assignable< as Sub>::Output>`, which in turn requires the `Future::Output` type to implement `Sub`. ```rust use futures_executor::block_on; let a = async { 44 }; let b = async { 2 }; let result = async { async_ops::assignable!(a); a -= b; a.await }; assert_eq!(42, block_on(result)); ```
## License Licensed under either of * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or ) * MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the [Apache License Version 2.0](LICENSE-APACHE), shall be dual licensed as above, without any additional terms or conditions.