net: add into_std for net types without it (#3509)

This commit is contained in:
Alice Ryhl 2021-02-06 23:01:47 +01:00 committed by GitHub
parent 6fd9084d47
commit 58bd242831
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 196 additions and 10 deletions

View File

@ -192,7 +192,6 @@ impl TcpListener {
/// backing event loop. This allows configuration of options like
/// `SO_REUSEPORT`, binding to multiple addresses, etc.
///
///
/// # Examples
///
/// ```rust,no_run
@ -221,6 +220,48 @@ impl TcpListener {
Ok(TcpListener { io })
}
/// Turn a [`tokio::net::TcpListener`] into a [`std::net::TcpListener`].
///
/// The returned [`std::net::TcpListener`] will have nonblocking mode set as
/// `true`. Use [`set_nonblocking`] to change the blocking mode if needed.
///
/// # Examples
///
/// ```rust,no_run
/// use std::error::Error;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn Error>> {
/// let tokio_listener = tokio::net::TcpListener::bind("127.0.0.1:0").await?;
/// let std_listener = tokio_listener.into_std()?;
/// std_listener.set_nonblocking(false)?;
/// Ok(())
/// }
/// ```
///
/// [`tokio::net::TcpListener`]: TcpListener
/// [`std::net::TcpListener`]: std::net::TcpListener
/// [`set_nonblocking`]: fn@std::net::TcpListener::set_nonblocking
pub fn into_std(self) -> io::Result<std::net::TcpListener> {
#[cfg(unix)]
{
use std::os::unix::io::{FromRawFd, IntoRawFd};
self.io
.into_inner()
.map(|io| io.into_raw_fd())
.map(|raw_fd| unsafe { std::net::TcpListener::from_raw_fd(raw_fd) })
}
#[cfg(windows)]
{
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
self.io
.into_inner()
.map(|io| io.into_raw_socket())
.map(|raw_socket| unsafe { std::net::TcpListener::from_raw_socket(raw_socket) })
}
}
pub(crate) fn new(listener: mio::net::TcpListener) -> io::Result<TcpListener> {
let io = PollEvented::new(listener)?;
Ok(TcpListener { io })

View File

@ -8,11 +8,6 @@ use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::net::{Shutdown, SocketAddr};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
use std::pin::Pin;
use std::task::{Context, Poll};
use std::time::Duration;
@ -199,7 +194,7 @@ impl TcpStream {
/// Turn a [`tokio::net::TcpStream`] into a [`std::net::TcpStream`].
///
/// The returned [`std::net::TcpStream`] will have `nonblocking mode` set as `true`.
/// The returned [`std::net::TcpStream`] will have nonblocking mode set as `true`.
/// Use [`set_nonblocking`] to change the blocking mode if needed.
///
/// # Examples
@ -234,6 +229,7 @@ impl TcpStream {
pub fn into_std(self) -> io::Result<std::net::TcpStream> {
#[cfg(unix)]
{
use std::os::unix::io::{FromRawFd, IntoRawFd};
self.io
.into_inner()
.map(|io| io.into_raw_fd())
@ -242,6 +238,7 @@ impl TcpStream {
#[cfg(windows)]
{
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
self.io
.into_inner()
.map(|io| io.into_raw_socket())
@ -932,11 +929,13 @@ impl TcpStream {
fn to_mio(&self) -> mio::net::TcpSocket {
#[cfg(windows)]
{
use std::os::windows::io::{AsRawSocket, FromRawSocket};
unsafe { mio::net::TcpSocket::from_raw_socket(self.as_raw_socket()) }
}
#[cfg(unix)]
{
use std::os::unix::io::{AsRawFd, FromRawFd};
unsafe { mio::net::TcpSocket::from_raw_fd(self.as_raw_fd()) }
}
}

View File

@ -209,6 +209,48 @@ impl UdpSocket {
UdpSocket::new(io)
}
/// Turn a [`tokio::net::UdpSocket`] into a [`std::net::UdpSocket`].
///
/// The returned [`std::net::UdpSocket`] will have nonblocking mode set as
/// `true`. Use [`set_nonblocking`] to change the blocking mode if needed.
///
/// # Examples
///
/// ```rust,no_run
/// use std::error::Error;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn Error>> {
/// let tokio_socket = tokio::net::UdpSocket::bind("127.0.0.1:0").await?;
/// let std_socket = tokio_socket.into_std()?;
/// std_socket.set_nonblocking(false)?;
/// Ok(())
/// }
/// ```
///
/// [`tokio::net::UdpSocket`]: UdpSocket
/// [`std::net::UdpSocket`]: std::net::UdpSocket
/// [`set_nonblocking`]: fn@std::net::UdpSocket::set_nonblocking
pub fn into_std(self) -> io::Result<std::net::UdpSocket> {
#[cfg(unix)]
{
use std::os::unix::io::{FromRawFd, IntoRawFd};
self.io
.into_inner()
.map(|io| io.into_raw_fd())
.map(|raw_fd| unsafe { std::net::UdpSocket::from_raw_fd(raw_fd) })
}
#[cfg(windows)]
{
use std::os::windows::io::{FromRawSocket, IntoRawSocket};
self.io
.into_inner()
.map(|io| io.into_raw_socket())
.map(|raw_socket| unsafe { std::net::UdpSocket::from_raw_socket(raw_socket) })
}
}
/// Returns the local address that this socket is bound to.
///
/// # Example

View File

@ -5,7 +5,7 @@ use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::net::Shutdown;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::net;
use std::path::Path;
use std::task::{Context, Poll};
@ -376,6 +376,36 @@ impl UnixDatagram {
Ok(UnixDatagram { io })
}
/// Turn a [`tokio::net::UnixDatagram`] into a [`std::os::unix::net::UnixDatagram`].
///
/// The returned [`std::os::unix::net::UnixDatagram`] will have nonblocking
/// mode set as `true`. Use [`set_nonblocking`] to change the blocking mode
/// if needed.
///
/// # Examples
///
/// ```rust,no_run
/// use std::error::Error;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn Error>> {
/// let tokio_socket = tokio::net::UnixDatagram::bind("127.0.0.1:0")?;
/// let std_socket = tokio_socket.into_std()?;
/// std_socket.set_nonblocking(false)?;
/// Ok(())
/// }
/// ```
///
/// [`tokio::net::UnixDatagram`]: UnixDatagram
/// [`std::os::unix::net::UnixDatagram`]: std::os::unix::net::UnixDatagram
/// [`set_nonblocking`]: fn@std::os::unix::net::UnixDatagram::set_nonblocking
pub fn into_std(self) -> io::Result<std::os::unix::net::UnixDatagram> {
self.io
.into_inner()
.map(|io| io.into_raw_fd())
.map(|raw_fd| unsafe { std::os::unix::net::UnixDatagram::from_raw_fd(raw_fd) })
}
fn new(socket: mio::net::UnixDatagram) -> io::Result<UnixDatagram> {
let io = PollEvented::new(socket)?;
Ok(UnixDatagram { io })

View File

@ -4,7 +4,7 @@ use crate::net::unix::{SocketAddr, UnixStream};
use std::convert::TryFrom;
use std::fmt;
use std::io;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::net;
use std::path::Path;
use std::task::{Context, Poll};
@ -88,6 +88,35 @@ impl UnixListener {
Ok(UnixListener { io })
}
/// Turn a [`tokio::net::UnixListener`] into a [`std::os::unix::net::UnixListener`].
///
/// The returned [`std::os::unix::net::UnixListener`] will have nonblocking mode
/// set as `true`. Use [`set_nonblocking`] to change the blocking mode if needed.
///
/// # Examples
///
/// ```rust,no_run
/// use std::error::Error;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn Error>> {
/// let tokio_listener = tokio::net::UnixListener::bind("127.0.0.1:0")?;
/// let std_listener = tokio_listener.into_std()?;
/// std_listener.set_nonblocking(false)?;
/// Ok(())
/// }
/// ```
///
/// [`tokio::net::UnixListener`]: UnixListener
/// [`std::os::unix::net::UnixListener`]: std::os::unix::net::UnixListener
/// [`set_nonblocking`]: fn@std::os::unix::net::UnixListener::set_nonblocking
pub fn into_std(self) -> io::Result<std::os::unix::net::UnixListener> {
self.io
.into_inner()
.map(|io| io.into_raw_fd())
.map(|raw_fd| unsafe { net::UnixListener::from_raw_fd(raw_fd) })
}
/// Returns the local socket address of this listener.
pub fn local_addr(&self) -> io::Result<SocketAddr> {
self.io.local_addr().map(SocketAddr)

View File

@ -9,7 +9,7 @@ use std::convert::TryFrom;
use std::fmt;
use std::io::{self, Read, Write};
use std::net::Shutdown;
use std::os::unix::io::{AsRawFd, RawFd};
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use std::os::unix::net;
use std::path::Path;
use std::pin::Pin;
@ -508,6 +508,51 @@ impl UnixStream {
Ok(UnixStream { io })
}
/// Turn a [`tokio::net::UnixStream`] into a [`std::os::unix::net::UnixStream`].
///
/// The returned [`std::os::unix::net::UnixStream`] will have nonblocking
/// mode set as `true`. Use [`set_nonblocking`] to change the blocking
/// mode if needed.
///
/// # Examples
///
/// ```
/// use std::error::Error;
/// use std::io::Read;
/// use tokio::net::UnixListener;
/// # use tokio::net::UnixStream;
/// # use tokio::io::AsyncWriteExt;
///
/// #[tokio::main]
/// async fn main() -> Result<(), Box<dyn Error>> {
/// let dir = tempfile::tempdir().unwrap();
/// let bind_path = dir.path().join("bind_path");
///
/// let mut data = [0u8; 12];
/// let listener = UnixListener::bind(&bind_path)?;
/// # let handle = tokio::spawn(async {
/// # let mut stream = UnixStream::connect(bind_path).await.unwrap();
/// # stream.write(b"Hello world!").await.unwrap();
/// # });
/// let (tokio_unix_stream, _) = listener.accept().await?;
/// let mut std_unix_stream = tokio_unix_stream.into_std()?;
/// # handle.await.expect("The task being joined has panicked");
/// std_unix_stream.set_nonblocking(false)?;
/// std_unix_stream.read_exact(&mut data)?;
/// # assert_eq!(b"Hello world!", &data);
/// Ok(())
/// }
/// ```
/// [`tokio::net::UnixStream`]: UnixStream
/// [`std::os::unix::net::UnixStream`]: std::os::unix::net::UnixStream
/// [`set_nonblocking`]: fn@std::os::unix::net::UnixStream::set_nonblocking
pub fn into_std(self) -> io::Result<std::os::unix::net::UnixStream> {
self.io
.into_inner()
.map(|io| io.into_raw_fd())
.map(|raw_fd| unsafe { std::os::unix::net::UnixStream::from_raw_fd(raw_fd) })
}
/// Creates an unnamed pair of connected sockets.
///
/// This function will create a pair of interconnected Unix sockets for