type Handler = fn(Request<Body>) -> Result<Response<Body>, Error>;
let mut map: HashMap<&str, Handler> = HashMap::new();
map.insert("/", |req| { Ok(Response::new("hello".into())) });
map.insert("/about", |req| { Ok(Response::new("about".into())) });
Sure, using function pointer `fn` instead of one of the Fn traits is a bit of a cheating, but realistically you wouldn't want a handler to be a capturing closure anyway. type Handler = Box<dyn Fn(Request) -> BoxFuture + Send + Sync>;
type BoxFuture = Pin<Box<dyn Future<Output = Result> + Send>>;
plus type params with trait bounds infecting every method you want pass your handler to, think get, post, put, patch, etc. pub fn add<H, F>(&mut self, path: &str, handler: H)
where
H: Fn(Request) -> F + Send + Sync + 'static,
F: Future<Output = Result> + Send + 'static,
And for what reason? I mean, look at the definitions fn(Request<Body>) -> Result<Response<Body>, Error>;
async fn(Request<Body>) -> Result<Response<Body>, Error>;
It would be reasonable to suggest that if the first one is flexible enough to be stored in a container without any fuss, then the second one should as well. As a user of the language, especially in the beginning, I do not want to know of and be penalized by all the crazy transformations that the compiler is doing behind the scene.
After living in Western Europe for almost a decade it's still shocking to me how much people here do not understand Russia.