Reputation: 3
While trying to create a simple webserver in Rocket, I ran into the problem that I wanted to redirect or send html data, depending on certain conditions as follows:
#[post("/test/<some_string>")]
// This doesn't work Redirect and Html are different types.
pub fn test(some_string: String) -> _ {
if validate(some_string) {
Redirect("/dashboard")
} else {
content::Html("<h1>Hello World</h1>")
}
}
This clearly doesn't work as Html
and Redirect
are clearly different types. Then I tried to create an enum with different responder types so I could use different responder types in the same function, this resulted in the following code:
pub enum TwoResponders<'r, T: Responder<'r>, V: Responder<'r>> {
ResponderOne(T),
ResponderTwo(V),
}
impl<'r, T: Responder<'r>, V: Responder<'r>> Responder<'r> for TwoResponders<'r, T, V> {
fn respond_to(self, request: &Request) -> response::Result<'r> {
match self {
TwoResponders::ResponderOne(responder) => responder.respond_to(request),
TwoResponders::ResponderTwo(responder) => responder.respond_to(request),
}
}
}
This however, didn't work either, because now the Rust compiler complains that the lifetime 'r
is unused in the struct TwoResponders
. I would think this is not the case as it is used in defining the traits T and V need to have, the Rust compiler thinks differently however, and it has the final word as always.
I was thinking of adding a PhantomData
however that seemed like an incredibly ugly solution for something which shouldn't be this difficult to my knowledge.
Is there a better way to fix this?
Upvotes: 0
Views: 156
Reputation: 40814
In cases like this, where the generic type bounds require some otherwise unused type parameter or lifetime and adding PhantomData
makes things unnecessarily ugly, I find it cleanest to just remove the type bounds entirely from the type itself, and only keep them on the impl
block:
pub enum TwoResponders<T, V> {
ResponderOne(T),
ResponderTwo(V),
}
impl<'r, T: Responder<'r>, V: Responder<'r>> Responder<'r> for TwoResponders<T, V> {
fn respond_to(self, request: &Request) -> response::Result<'r> {
match self {
TwoResponders::ResponderOne(responder) => responder.respond_to(request),
TwoResponders::ResponderTwo(responder) => responder.respond_to(request),
}
}
}
Upvotes: 3