cb_fut
This crate provide utility macros to convert a call to function that need a callback to handle return values into a function that either return a Future
that resolve to values or a Stream
that yield values. It introduce extra syntax -> ()
into functional call signature.
Limitation
Following are limitations of this crate.
- If the callback is not intended to return a value, don't use these two macros. It'll break the function.
- If the function also return value, the returned value will be silently dropped.
- The macro support only single callback conversion. If the function take more than one callbacks to return value on different circumstances, it cannot be use.
- It will be slower compare to using original callback. This is because it require some kind of indirection to direct a callback through channel into a
Future
.
How to use
This crate provide two macros.
once
- for convert a call to a function with a callback into aFuture
that resolve to values which used to be return as callback parameters.stream
- for convert a call to a function with a callback into aStream
that yield values which usually pass to callback as parameters.
The main difference between the two is once
shall be used if a callback will be called exactly once while stream
shall be used if a callback will be called multiple times.
These two macro need a special syntax to identify number of expected return variables. The syntax is -> ()
which resemble the function signature for returning type, e.g. Fn(i32) -> ()
.
These conversion result in Future
that resolve to tuple of values. See examples below.
Examples
Turn a function with callback on last parameter into a future.
// A function that need a callback
// Use once! to convert the call to `func` to return a `Future` instead.
// We use ->(a, b) to tell macro that `Future` shall return two variables.
let = block_on;
assert_eq!;
assert_eq!;
The callback can be in anywhere in function signature. The callback placeholder just need to reflect that too.
// A function that put callback in the middle between other two parameters
// We use `->(a, b)` between 1, and, 2 + 3 to tell macro that this parameter is a callback and it take 2 parameters.
let = block_on;
assert_eq!;
assert_eq!;
In case the callback take no argument, we need to put -> ()
// a function that take no arguments callback
// A callback placeholder with no argument
block_on;
If callback will be called multiple times, use stream!
use StreamExt;
// A function that take callback as first argument.
// It'll call callback 5 times with two arguments, an original value and the original value times number of called.
let mut counter = 0;
// `stream!` will return `CBStream` which implement `Stream` trait. We use `enumerate` and `for_each` from `StreamExt` trait to iterate over each values tuples that suppose to be passed to callback function.
// The `for_each` method signature require a return value of type `Future` for given callback. The final return value from `for_each` is a single consolidated `Future` which when resolve, all `Future`s inside it are all resolved.
block_on;
assert_eq!;