Returning complex types

I started dabbling a bit with hyper to see if I could get a simple web server up and running.

Since I want my main function clean I created a function:

fn create_backend() -> ????? {
        let address: SocketAddr = "0.0.0.0:8080".parse().expect("Failed to parse address");

        let service = || service_fn_ok(|req| Response::new(Body::from("Hello World")));

        Server::bind(&address).serve(service)
}

Which I would call from main:

fn main() {
      let server = create_backend();
      hyper:rt::run(server)
}

I'm having a lot of trouble constructing the return type for create_backend(), there seem to be a lot of digging into hyper to understand how the Server-object is constructed. Also there are closures in the signature.

How should it be?

And in more general terms, what is the best strategy when dealing with complex return types? It seems like it would come up over and over again. I've found out that you can also return -> impl SomeTrait, but when an external crate (hyper) hasn't defined a trait for it's return type, it doesn't seem that useful.

Anyway, would really appreciate some help here.

1 Like

Server::bind(&address).serve(service) returns Server, and Server implements Future with the associated types Item = () and Error = hyper::Error (click the [+] next to the implementation to see this info).

Therefore, you should be able to return impl Future<Item = (), Error = hyper::Error>.

Note that you won't be able to run a Future<Item = (), Error = hyper::Error> on the runtime directly, as hyper::rt::run expects a Future<Item = (), Error = ()>. This is to force you to handle any errors that arise. See the example in the docs for one way to handle this - note that they have a map_err that doesn't return anything, but just logs errors out.

3 Likes

Thanks! I must have missed the Future Trait in the docs, or not understanding that was what I needed (actually I think I might have looked at the server module doc rather than the struct). The compiler error wanted Server<I, S, E> so that also helped to confuse things.

I got it to work according to your suggestions!

Just curious, what is the deal with impl Future<Item = (), Error = hyper::Error>. I initially just tried impl Future which kinda worked but it complained about the Item not matching ().

I'm not 100% sure why impl Future alone didn't work (tried your code myself and the error message was a bit confusing) - hopefully someone with better async-fu than I will be able to explain :slight_smile:

I think the Item is the value the future returns when eventually done. So () would indicate that we just resolve it without a value. It makes sense to me now, although maybe I would have expeceted impl Future to have () as it's default Item.