rust - 如何将 hyper::server::Server 作为字段存储在结构中?
问题描述
我有一个在内部使用 hyper 的库。我希望用户能够创建一个App
包含Server
处理 HTTP 连接的内部。
use hyper::server::conn::AddrIncoming;
use hyper::server::Server;
use hyper::service::service_fn_ok;
use std::net::SocketAddr;
pub struct App {
inner: Server<AddrIncoming, ()>,
}
impl App {
pub fn new() -> Self {
let addr = SocketAddr::from(([0, 0, 0, 0], 3000));
let inner = Server::bind(&addr).serve(|| service_fn_ok(|_req| unimplemented!()));
App { inner }
}
}
(游乐场链接)
正如预期的那样,错误是:
error[E0308]: mismatched types
--> src/lib.rs:15:15
|
15 | App { inner }
| ^^^^^ expected (), found closure
|
= note: expected type `hyper::server::Server<_, ()>`
found type `hyper::server::Server<_, [closure@src/lib.rs:13:47: 13:88]>`
它没有很好的记录,但第二个类型参数Server
是MakeService
它使用的类型。
我不知道如何在inner
. 有什么方法可以让我可以将闭包装箱以使代码编译?有没有办法MakeService
手动实现,而不是使用闭包?
超文档引用了函数make_service_fn
,它返回 a MakeServiceFn
,但类型不是公共的,所以我不能在inner
.
解决方案
问题是由于类型不匹配造成的。在 Rust 中,类型参数是结构类型的一部分,因此结构中服务器的类型参数必须与您在结构中定义的类型参数匹配。在你的情况下,他们没有。
您的问题有 2 个解决方案。
将第二个服务器参数的类型参数添加到您的结构
pub struct App<T> {
inner: Server<AddrIncoming, T>,
}
现在您将能够为服务器的第二个类型参数创建具有不同类型的应用程序
查找您正在创建的服务器的第二个参数的类型
在您的情况下,第二个参数的类型是 ``,因此您可以像这样声明您的结构:
type Service = ?; // This is really hard to find in this case.
pub struct App {
inner: Server<AddrIncoming, Service>,
}
结论
在你的情况下,我会推荐第一个,因为第二个类型参数的类型Server
很难找到,并且在你的程序开发过程中很可能会发生变化,所以在你的结构上只有一个类型参数要容易得多。
但是,如果您不知道服务器的类型参数没有实现某些特征,有时您将无法在服务器上使用某些方法,因此您可以将这些特征添加到您的类型参数中,如下所示:
pub struct App<T: Service> {
inner: Server<AddrIncoming, T>,
}
建议不要将类型参数放在结构本身上,而只将它们放在impl
块上:
pub struct App<T> {
inner: Server<AddrIncoming, T>,
}
impl App<T: Service> {
// Here you'll be able to use the method from Server where T has to be a Service.
}
你也可以对这样的函数做同样的事情:
pub struct App<T> {
inner: Server<AddrIncoming, T>,
}
fn some_function(app: App<T: Service>) {
// Here you'll be able to use the method from Server where T has to be a Service
}