如何将 hyper::server::Server 存储为结构中的字段? [英] How to store a hyper::server::Server as a field in a struct?

查看:31
本文介绍了如何将 hyper::server::Server 存储为结构中的字段?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在内部使用 hyper 的库.我希望用户能够创建一个 App,其中包含一个在内部处理 HTTP 连接的 Server.

I have a library which uses hyper internally. I want the user to be able to create an Appwhich contains a Server internally that handles HTTP connections.

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

(游乐场链接)

错误是,正如预期的那样:

The error is, as expected:

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.

It's not well documented, but the second type parameter for Server is the kind of MakeService it uses.

我不知道如何引用 inner 类型的闭包.有什么方法可以将闭包装箱以使代码编译?有没有办法手动实现 MakeService 而不是使用闭包?

I can't figure out how to refer to the closure in the type of inner. Is there some way that I can box the closure to make the code compile? Is there a way to implement MakeService by hand, instead of using a closure?

hyper docs 引用了函数 make_service_fn,它返回一个 MakeServiceFn,但是类型不是公共的,所以我不能在类型中使用它内部.

The hyper docs refer to the function make_service_fn, which returns a MakeServiceFn, but the type isn't public, so I can't use it in the type of inner.

推荐答案

问题是由于类型不匹配造成的.在 Rust 中,类型参数是结构类型的一部分,因此结构中服务器的类型参数必须与您在结构中定义的类型参数相匹配.在你的情况下,他们没有.

The problem is due to a type mismatch. In Rust, a type parameter is part of the type of a struct, so the type parameters for the server in your struct must match the ones you defined in your struct. In your case they don't.

您的问题有两种解决方案.

There are 2 solutions to your problem.

pub struct App<T> {
    inner: Server<AddrIncoming, T>,
}

现在您可以为服务器的第二个类型参数创建不同类型的应用

Now you'll be able to create apps with different types for the second type parameter of the server

在你的例子中,第二个参数的类型是``,所以你可以像这样声明你的结构:

In your case, the type of the second argument is ``, so you would declare your struct like this:

type Service = ?; // This is really hard to find in this case.
pub struct App {
    inner: Server<AddrIncoming, Service>,
}

结论

在你的情况下,我会推荐第一个,因为 Server 的第二个类型参数的类型很难找到,并且在你的程序开发过程中很可能会改变,所以它更容易只需在结构上有一个类型参数.

Conclusion

In your case, I would recommend the first one because the type of the second type parameter of Server is hard to find and could very well change during the development of your program, so it's much easier to just have a type parameter on your struct.

但是,有时如果您不知道它的类型参数没有实现某些特征,则有时您将无法在服务器上使用某些方法,因此您可以将这些特征添加到您的类型参数中,如下所示:

However, sometimes you won't be able to use certain method on your server if you don't know that its type parameters don't implement certain traits, so you can add these traits to your type parameter like this:

pub struct App<T: Service> {
    inner: Server<AddrIncoming, T>,
}

建议不要把类型参数放在结构体本身,而只放在impl块上:

It is recommended not to put the type parameters on the struct itself and to only put them on the impl blocks:

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.
}

你也可以对这样的函数做同样的事情:

You can also do the same for functions like this:

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
}

这篇关于如何将 hyper::server::Server 存储为结构中的字段?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆