]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #88339 - piegamesde:master, r=joshtriplett
authorYuki Okushi <jtitor@2k36.org>
Fri, 17 Sep 2021 05:09:45 +0000 (14:09 +0900)
committerGitHub <noreply@github.com>
Fri, 17 Sep 2021 05:09:45 +0000 (14:09 +0900)
Add TcpListener::into_incoming and IntoIncoming

The `incoming` method is really useful, however for some use cases the borrow
this introduces is needlessly restricting. Thus, an owned variant is added.

r? ``@joshtriplett``

library/std/src/net/tcp.rs

index 5b4a9fa7979de644cb0cc043114071cc53dfb480..223726d45d72a4ffe7ee2ad5897c7e97575cbbda 100644 (file)
@@ -96,6 +96,18 @@ pub struct Incoming<'a> {
     listener: &'a TcpListener,
 }
 
+/// An iterator that infinitely [`accept`]s connections on a [`TcpListener`].
+///
+/// This `struct` is created by the [`TcpListener::into_incoming`] method.
+/// See its documentation for more.
+///
+/// [`accept`]: TcpListener::accept
+#[derive(Debug)]
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+pub struct IntoIncoming {
+    listener: TcpListener,
+}
+
 impl TcpStream {
     /// Opens a TCP connection to a remote host.
     ///
@@ -845,6 +857,37 @@ pub fn incoming(&self) -> Incoming<'_> {
         Incoming { listener: self }
     }
 
+    /// Turn this into an iterator over the connections being received on this
+    /// listener.
+    ///
+    /// The returned iterator will never return [`None`] and will also not yield
+    /// the peer's [`SocketAddr`] structure. Iterating over it is equivalent to
+    /// calling [`TcpListener::accept`] in a loop.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(tcplistener_into_incoming)]
+    /// use std::net::{TcpListener, TcpStream};
+    ///
+    /// fn listen_on(port: u16) -> impl Iterator<Item = TcpStream> {
+    ///     let listener = TcpListener::bind("127.0.0.1:80").unwrap();
+    ///     listener.into_incoming()
+    ///         .filter_map(Result::ok) /* Ignore failed connections */
+    /// }
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     for stream in listen_on(80) {
+    ///         /* handle the connection here */
+    ///     }
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+    pub fn into_incoming(self) -> IntoIncoming {
+        IntoIncoming { listener: self }
+    }
+
     /// Sets the value for the `IP_TTL` option on this socket.
     ///
     /// This value sets the time-to-live field that is used in every packet sent
@@ -982,6 +1025,14 @@ fn next(&mut self) -> Option<io::Result<TcpStream>> {
     }
 }
 
+#[unstable(feature = "tcplistener_into_incoming", issue = "88339")]
+impl Iterator for IntoIncoming {
+    type Item = io::Result<TcpStream>;
+    fn next(&mut self) -> Option<io::Result<TcpStream>> {
+        Some(self.listener.accept().map(|p| p.0))
+    }
+}
+
 impl AsInner<net_imp::TcpListener> for TcpListener {
     fn as_inner(&self) -> &net_imp::TcpListener {
         &self.0