It's too late but I hope this code helps others. In my situation I have some predefined functions which I can not change them (func0, func1, ...) and I need to run them all till the last one in order. If one fails, the whole operation must terminate. So I created an array of functions, then each item will get executed during a loop.
use std::future::Future;
use std::pin::Pin;
type FuncResult = dyn Future<Output=Result<(), String>>;
async fn apply_funcs(mut start: usize, end: usize) {
let funcs = [func0];
let mut result = true;
while start < end && result {
result = func_wrapper(funcs[start]).await;
start += 1;
}
}
async fn func_wrapper(f: impl FnOnce() -> FuncResult) -> bool {
match f().await {
Ok(_) => { println!("ok"); }
Err(e) => {
println!("{e}");
return false;
}
}
true
}
async fn func0() -> Result<(), String> {
todo!()
}
This code fails: expected dyn Future
, found future
I found 2 ways to solve that:
1: By static dispatching which is by generics:
async fn apply_funcs(mut start: usize, end: usize) {
let funcs = [func0];
let mut result = true;
while start < end && result {
result = func_wrapper(funcs[start]).await;
start += 1;
}
}
async fn func_wrapper<Fut>(f: impl FnOnce() -> Fut) -> bool
where Fut: Future<Output=Result<(), String>> {
match f().await {
Ok(_) => { println!("ok"); }
Err(e) => {
println!("{e}");
return false;
}
}
true
}
async fn func0() -> Result<(), String> {
todo!()
}
2: By dynamic dispatching via defining another closure:
type FuncResult = Pin<Box<dyn Future<Output=Result<(), String>>>>;
async fn apply_funcs(mut start: usize, end: usize) {
let funcs = [
|| -> FuncResult {
Box::pin(func0())// no await here
}
];
let mut result = true;
while start < end && result {
result = func_wrapper(funcs[start]).await;
start += 1;
}
}
async fn func_wrapper(f: impl FnOnce() -> FuncResult) -> bool {
match f().await {
Ok(_) => { println!("ok"); }
Err(e) => {
println!("{e}");
return false;
}
}
true
}
async fn func0() -> Result<(), String> {
todo!()
}