0

在尝试在 Rocket 中创建一个简单的网络服务器时,我遇到了我想要重定向发送 html 数据的问题,具体取决于以下某些条件:

#[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>")
    }
}

这显然不起作用,Html并且Redirect显然是不同的类型。然后我尝试创建一个具有不同响应者类型的枚举,这样我就可以在同一个函数中使用不同的响应者类型,这导致了以下代码:

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),
        }
    }
}

然而,这也不起作用,因为现在 Rust 编译器抱怨生命周期'r在 struct 中未使用TwoResponders。我认为情况并非如此,因为它用于定义 T 和 V 需要具有的特征,但是 Rust 编译器的想法不同,并且它一如既往地拥有最终决定权。

我正在考虑添加一个PhantomData似乎是一个非常丑陋的解决方案,但据我所知,这不应该如此困难。

有没有更好的方法来解决这个问题?

4

1 回答 1

3

在这种情况下,泛型类型边界需要一些其他未使用的类型参数或生命周期,并且添加PhantomData会使事情变得不必要地丑陋,我发现从类型本身中完全删除类型边界并仅将它们保留在impl块上是最干净的:

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),
        }
    }
}
于 2020-08-12T00:12:50.437 回答