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