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

后端 未结 1 866
不思量自难忘°
不思量自难忘° 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 Pin>>>;
    

    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 = Result>;
    type CalcFn = Box LocalBoxFuture<'static, BoxedResult>>;
    
    async fn add(a: i32, b: i32) -> BoxedResult {
        Ok(a + b)
    }
    
    async fn sub(a: i32, b: i32) -> BoxedResult {
        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)
提交回复
热议问题