How to store hyper::server::Server with a default handler as a struct field in a constructor?

Viewed 443

I am trying to store a hyper::server::Server as a member of my struct (struct MyApp below). I can do this from, for example, my program's main() function.

How can I do this in my struct's MyApp::new() method? I think I need the concrete type for F in MyApp<F>. However, despite trying, I am unable to (correctly) specify a concrete type for this closure.

I can't figure out how to do this. I thought Boxing the closure would work by allowing me to pass the closure as a concrete type, and indeed it does when I do this in main(), but not MyApp::new(). I am hoping there is a way to do this in stable rust, as I would really like to implement a structure which contains a hyper Server.

Here is my struct:

struct MyApp<F> {
    hyper_server: Server<MyBoxedClosure<F>, hyper::Body>,
}

And here is the full code that works -- it sets the MyApp.hyper_server field in main():

extern crate hyper;
extern crate futures;
use hyper::Error;
use hyper::server::{Http, Server, NewService, Service, Request, Response};
use hyper::header::ContentLength;

pub struct HelloWorld;

const PHRASE: &'static str = "Hello, World!";

impl Service for HelloWorld {
    type Request = Request;
    type Response = Response;
    type Error = hyper::Error;
    type Future = futures::future::FutureResult<Self::Response, Self::Error>;

    fn call(&self, _req: Request) -> Self::Future {
        futures::future::ok(
            Response::new()
                .with_header(ContentLength(PHRASE.len() as u64))
                .with_body(PHRASE),
        )
    }
}

pub struct MyBoxedClosure<F> {
    value: Box<F>,
}

impl<F> NewService for MyBoxedClosure<F>
where
    F: Fn() -> std::result::Result<HelloWorld, std::io::Error>,
{
    type Request = Request;
    type Response = Response;
    type Error = Error;
    type Instance = HelloWorld;

    fn new_service(&self) -> std::result::Result<Self::Instance, std::io::Error> {
        self.value.new_service()
    }
}

struct MyApp<F> {
    hyper_server: Server<MyBoxedClosure<F>, hyper::Body>,
}

fn main() {
    let mbc = MyBoxedClosure { value: Box::new(|| Ok(HelloWorld)) };
    let addr = "127.0.0.1:3000".parse().unwrap();
    let hyper_server = Http::new().bind(&addr, mbc).unwrap();
    let my_app = MyApp { hyper_server: hyper_server };

    println!("Hello, world!");
}

If I create a MyApp::new() function and call that from the main() instead, I can't figure out how to avoid a compiler error.

impl<F> MyApp<F>
where
    F: Fn() -> std::result::Result<HelloWorld, std::io::Error> + Send + Sync,
{
    fn new() -> MyApp<F> {
        let mbc = MyBoxedClosure { value: Box::new(|| Ok(HelloWorld)) };
        let addr = "127.0.0.1:3000".parse().unwrap();
        let hyper_server = Http::new().bind(&addr, mbc).unwrap();
        MyApp { hyper_server: hyper_server }
    }
}

fn main() {
    let _my_app = MyApp::new();
    println!("Hello, world!");
}

The compiler error is this:

error[E0308]: mismatched types
  --> src/main.rs:56:9
   |
56 |         MyApp { hyper_server: hyper_server }
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter, found closure
   |
   = note: expected type `MyApp<F>`
              found type `MyApp<[closure@src/main.rs:53:52: 53:69]>`
0 Answers
Related