I cannot handle async functions when writing an async router for hyper
.
This code:
use std::collections::HashMap;
use std::future::Futur
This happens because impl Future
is a concrete unique type while dyn Future
is an abstract type. HashMap
expects the abstract type since it can only hold instances of a single type.
If we can box the return type of the async functions, we will able to add these futures into a HashMap
.
First we need to change the type of CalcFn
:
type CalcFn = Box<dyn Fn(i32, i32) -> Pin<Box<dyn Future<Output = i32>>>>;
Then this can do the trick:
let mut map: HashMap<&str, CalcFn> = Default::default();
map.insert("add", Box::new(|a, b| Box::pin(add(a, b))));
map.insert("sub", Box::new(|a, b| Box::pin(sub(a, b))));
println!("map size: {}", map.len());
//map.get("add").unwrap()(2, 3).await
This complete example
simplified Future
's Item
type, using an i32
instead of a Result
. Please also check the full code for your case.
You can also use types from the futures crate like LocalBoxFuture and BoxFuture created by the FutureExt::boxed and FutureExt::boxed_local methods respectively:
use futures::future::{FutureExt, LocalBoxFuture}; // 0.3.5
use std::collections::HashMap;
type BoxedResult<T> = Result<T, Box<dyn std::error::Error + Send + Sync>>;
type CalcFn = Box<dyn Fn(i32, i32) -> LocalBoxFuture<'static, BoxedResult<i32>>>;
async fn add(a: i32, b: i32) -> BoxedResult<i32> {
Ok(a + b)
}
async fn sub(a: i32, b: i32) -> BoxedResult<i32> {
Ok(a - b)
}
async fn example() {
let mut map: HashMap<&str, CalcFn> = Default::default();
map.insert("add", Box::new(|a, b| add(a, b).boxed()));
map.insert("sub", Box::new(|a, b| sub(a, b).boxed()));
println!("map size: {}", map.len());
//map.get("add").unwrap()(2, 3).await
}