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