Passing large data around inside of Iron routes?

i have a question that I think is a result of me being a noob.

I am building an application using Iron and Iron::router and I have a phat data struct that is expensive to copy. Multiple routes need this data, and I would like to pass it around without copying it.

In order to solve this, I made a wrapper struct called Handlers and impl'd methods for it, as my handlers. These all take a reference to &self , so I can access this phat data. However, it seems router.get doesn't allow methods, only functions? I put together a sort of minimal example:


/** A struct that contains a very large dictionary (literally, webster's) in memory
  * and provides handlers for the router as methods.
  */
pub struct Handlers {
    dict: Dictionary
}
impl Handlers {
    /// The homepage.
    pub fn home(_req: &mut Request) -> IronResult<Response> {
        let resp = Response::with((status::Ok, templates::homepage()));
        return Ok(resp);
	}
    
    /// Look up a character in the dictionary.
    pub fn lookup(&self, req: &mut Request) -> IronResult<Response> {
        return Ok(templates::details_page(self.dict.find( /* extract query out of request */ )));
    }
}

fn main() {
    // Build the phat dictionary struct
    let dict = Dictionary::new();
    // Create the handlers struct
    let handlers = Handlers { dict: dict };


    // Below is where I get the error:
    // attempted to take value of method `home` on type `handlers::Handlers`
    // and
    //  attempted to take value of method `lookup` on type `handlers::Handlers
    // help: use parentheses to call the method: `character_lookup(...)`
    let mut router = Router::new();
    router.get("/", handlers.home, "home");
    router.get("/lookup/:term", handlers.lookup, "lookup");
}

When you write fn home(_req: &mut Request) -> ... you are making an associated method, and it is called like this: Handlers::home(request). This is because there is not self parameter to the function.

I would propose putting your dictionary in an Arc, creating a clone (this only clones the Arc, so now you have two handles to the same object), and creating a move closure for each route, that moves each copy into the closure.

Thanks for the response. this approach works, but I find myself having to re-clone the arc in between every usage of the reference to the dictionary. This feels like I'm still barking up the wrong tree stylistically, even though it works.

    let dict_arc = Arc::clone(&dict);
    let mut router = Router::new();
    router.get( ..., handler(&dict_arc));
    let dict_arc = Arc::clone(&dict);
    router.get( ..., handler(&dict_arc));
    let dict_arc = Arc::clone(&dict);
    router.get( ..., handler(&dict_arc));

It doesn't seem to be tied to routes at all. You could just use lazy_static and save yourself all those arc references.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.