Как сохранить гипер :: сервер :: сервер как поле в структуре? - PullRequest
0 голосов
/ 06 июня 2019

У меня есть библиотека, которая использует гипер внутри.Я хочу, чтобы пользователь мог создать 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, которая возвращает MakeServiceFn, но тип не является общедоступным,поэтому я не могу использовать его в типе inner.

1 Ответ

0 голосов
/ 07 июня 2019

Проблема связана с несовпадением типов. В 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
}
...