How to define a type which has got runtime-only known type parameter?


#1

Working with a variable of type hyper::client::Client I faced a case, which I do not know how to handle in the rusty way. Could you please explain how to define the type for the property to support the following scenario (pseudo-code below, I used ? at the place where I do not know how to define it correctly):

struct Proxy {
    client: hyper::client::Client<?>
}

impl Proxy {
    fn new(url: String) -> Proxy {
        if (url.starts_with("https")) {
            let https = hyper_tls::HttpsConnector::new(1).unwrap();
            // this returns Client<HttpsConnector<HttpConnector>>
            return Proxy {
                client: hyper::client::Client::builder().build::<_, hyper::Body>(https)
            };
        }
        else {
            // this returns Client<HttpConnector>
            return Proxy {
                client: hyper::client::Client::new()
            };
        }
    }
}


#2

HttpsConnector can also connect to http URLs - just always use that type.


#3

Assuming you couldn’t (or didn’t want to) do what @sfackler suggested above, the easiest would be to make your own enum that covers the two types. Then expose/delegate Client functionality to the variant in use.

Otherwise, the typical answer for runtime polymorphism is trait objects. So in theory you’d do hyper::client::Client<Box<Connect>>. This doesn’t work, AFAICT, because there’s no Connect impl for Box<Connect>. You also can’t write just Box<Connect> - you’d need to provide the concrete type of all Connect’s associated types. And then some of those aren’t the same across http and https connectors. So probably you’d go back to the enum approach :slight_smile:.


#4

Thanks. I applied enums, but thought if there is better way…


#5

This is at best complimentary, rather than a better way, but request_dialog is an example of a function that is generic over the Client and Connect types you have. I did it this way (despite the good point that HttpsConnector works for both schemes) because I wanted this function to be usable without the full set of *-tls dependencies, if desired.