How can I put an async function into a map in Rust?

后端 未结 1 850
不思量自难忘°
不思量自难忘° 2020-11-30 11:45

I cannot handle async functions when writing an async router for hyper.

This code:

use std::collections::HashMap;
use std::future::Futur         


        
相关标签:
1条回答
  • 2020-11-30 11:57

    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
    }
    
    0 讨论(0)
提交回复
热议问题