hyper/server/
accept.rs

1//! The `Accept` trait and supporting types.
2//!
3//! This module contains:
4//!
5//! - The [`Accept`](Accept) trait used to asynchronously accept incoming
6//!   connections.
7//! - Utilities like `poll_fn` to ease creating a custom `Accept`.
8
9use std::pin::Pin;
10use std::task::{Context, Poll};
11
12#[cfg(feature = "stream")]
13use futures_core::Stream;
14#[cfg(feature = "stream")]
15use pin_project_lite::pin_project;
16
17/// Asynchronously accept incoming connections.
18pub trait Accept {
19    /// The connection type that can be accepted.
20    type Conn;
21    /// The error type that can occur when accepting a connection.
22    type Error;
23
24    /// Poll to accept the next connection.
25    fn poll_accept(
26        self: Pin<&mut Self>,
27        cx: &mut Context<'_>,
28    ) -> Poll<Option<Result<Self::Conn, Self::Error>>>;
29}
30
31/// Create an `Accept` with a polling function.
32///
33/// # Example
34///
35/// ```
36/// use std::task::Poll;
37/// use hyper::server::{accept, Server};
38///
39/// # let mock_conn = ();
40/// // If we created some mocked connection...
41/// let mut conn = Some(mock_conn);
42///
43/// // And accept just the mocked conn once...
44/// let once = accept::poll_fn(move |cx| {
45///     Poll::Ready(conn.take().map(Ok::<_, ()>))
46/// });
47///
48/// let builder = Server::builder(once);
49/// ```
50pub fn poll_fn<F, IO, E>(func: F) -> impl Accept<Conn = IO, Error = E>
51where
52    F: FnMut(&mut Context<'_>) -> Poll<Option<Result<IO, E>>>,
53{
54    struct PollFn<F>(F);
55
56    // The closure `F` is never pinned
57    impl<F> Unpin for PollFn<F> {}
58
59    impl<F, IO, E> Accept for PollFn<F>
60    where
61        F: FnMut(&mut Context<'_>) -> Poll<Option<Result<IO, E>>>,
62    {
63        type Conn = IO;
64        type Error = E;
65        fn poll_accept(
66            self: Pin<&mut Self>,
67            cx: &mut Context<'_>,
68        ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
69            (self.get_mut().0)(cx)
70        }
71    }
72
73    PollFn(func)
74}
75
76/// Adapt a `Stream` of incoming connections into an `Accept`.
77///
78/// # Optional
79///
80/// This function requires enabling the `stream` feature in your
81/// `Cargo.toml`.
82#[cfg(feature = "stream")]
83pub fn from_stream<S, IO, E>(stream: S) -> impl Accept<Conn = IO, Error = E>
84where
85    S: Stream<Item = Result<IO, E>>,
86{
87    pin_project! {
88        struct FromStream<S> {
89            #[pin]
90            stream: S,
91        }
92    }
93
94    impl<S, IO, E> Accept for FromStream<S>
95    where
96        S: Stream<Item = Result<IO, E>>,
97    {
98        type Conn = IO;
99        type Error = E;
100        fn poll_accept(
101            self: Pin<&mut Self>,
102            cx: &mut Context<'_>,
103        ) -> Poll<Option<Result<Self::Conn, Self::Error>>> {
104            self.project().stream.poll_next(cx)
105        }
106    }
107
108    FromStream { stream }
109}