Reputation: 545
I am going to use generic
to pass A<B<C>>>> and Z<A<B<C>>>> to a function as one type. But I don't know how to implement trait bounds
for this. The detail are as follows.
http
service and https
service each have listener and poll for accept. When an accept request comes in, handle_request()
is called to process the request.
The http
and https
request processing methods are the same, but in the case of https
, TlsService
is additionally implemented to include tls
processing. As a result, it has the following structure:
pub type RawRequest = HttpService<AccessLog<RouteService<CorsService<ProxyService>>>>;
pub struct Services {
http_service: Arc<RawRequest>,
https_service: Arc<TlsService<RawRequest>>,
http_accept_service: AcceptService,
https_accept_service: AcceptService,
}
...
fn handle_request<S>(stream: TcpStream, accesslog_sender: crossbeam_channel::Sender<String>, http_service: S) {
let connection = NewConnection {
stream,
service_builder: ServiceBuilder::new(),
};
tokio::spawn(async move {
ACCESSLOG_SENDER
.scope(accesslog_sender, async move {
if let Err(_e) = http_service.call(connection).await {
// TODO: write error
};
})
.await;
});
}
handle_request(stream, accesslog_sender, services.http_accept_service.clone());
handle_request(stream, accesslog_sender, services.https_accept_service.clone());
I am going to use generic to call the same function for different types of Service.
fn handle_request<S>(
stream: TcpStream,
accesslog_sender: crossbeam_channel::Sender<String>,
http_service: S,
) {
...
}
But I get a trait bound error.
error[E0599]: no method named `call` found for type parameter `S` in the current scope
I'm new to Rust and I'm struggling with generic
and trait bound
. Please help me how to write
Upvotes: 0
Views: 180
Reputation: 1858
When you use a generic type like S
rust will not make any assumptions about that type (expect that it has a compile time known size). Therefore you cannot really do anything on that type. For the compiler there is no way to know that a call()
method exists.
This is different from how C++ handles generics where you would get long and hard to read compiler errors when using a type for S
which does not have all the functionality used by the generic function.
The solution in Rust is a trait
. Lets suppose both your http and https service have a call
function. You can then write a trait (or more likely use one from the library your using) which says that these types have a call
method. You can then use this trait as a trait bound
in your function like this: handle_request<S : Name_of_the_trait>
This tells the compiler to only use types as a substitute for S
which implement Name_of_the_trait
and therefore you can call all the functions of this trait on S
.
I guess you should read more about traits and it should become apparent what you should do in detail. https://doc.rust-lang.org/stable/book/ch10-00-generics.html
Upvotes: 1