I'm trying to declare my routes with closures:
use mongodb::Client;
pub fn get_user_routes(client: Client) -> Router {
let controller = controller::UserController::new(client);
let handler = handlers::UserHandler::new(controller);
router!(
index: get "/" => move |r: &mut Request| handler.index(r),
show: get "/:id" => move |r: &mut Request| handler.show(r),
)
}
I get this error and I can't implement the Copy
trait for my UserController
because the mongodb::Client
doesn't implement it (it's an Arc
).
error[E0382]: capture of moved value: `handler`
--> src/api/users/mod.rs:17:57
|
16 | index: get "/" => move |r: &mut Request| handler.index(r),
| ---------------------- value moved (into closure) here
17 | show: get "/:id" => move |r: &mut Request| handler.show(r),
| ^^^^^^^ value captured here after move
|
= note: move occurs because `handler` has type `api::users::handlers::UserHandler`, which does not implement the `Copy` trait
My UserHandler
just has a UserController
and the UserController
, a mongodb::Client
.
The router get
method takes a handler by value. In Rust, passing by value implies giving up ownership.
By definition, you cannot give up ownership of something twice: it's no longer yours after you gave it up the first time! The only exception to the rule is Copy
types, but those are restricted to things like integers and non-mutating references (and references are out because Handler: 'static
).
Thus, you need to call .clone()
on the handler to be passed. Every time.
A very simple way is to use a block-expression:
let h = handler;
router!(
index: get "/" => { let h = h.clone(); move |r: &mut Request| h.index(r) },
show: get "/:id" => { let h = h.clone(); move |r: &mut Request| h.show(r) },
)
this way, you do not have to declare all the clones beforehand.