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 use std::pin::Pin;
10 use std::task::{Context, Poll};
11 
12 #[cfg(feature = "stream")]
13 use futures_core::Stream;
14 #[cfg(feature = "stream")]
15 use pin_project_lite::pin_project;
16 
17 /// Asynchronously accept incoming connections.
18 pub 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.
poll_accept( self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Option<Result<Self::Conn, Self::Error>>>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 /// ```
poll_fn<F, IO, E>(func: F) -> impl Accept<Conn = IO, Error = E> where F: FnMut(&mut Context<'_>) -> Poll<Option<Result<IO, E>>>,50 pub fn poll_fn<F, IO, E>(func: F) -> impl Accept<Conn = IO, Error = E>
51 where
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")]
from_stream<S, IO, E>(stream: S) -> impl Accept<Conn = IO, Error = E> where S: Stream<Item = Result<IO, E>>,83 pub fn from_stream<S, IO, E>(stream: S) -> impl Accept<Conn = IO, Error = E>
84 where
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 }
110