From 4b5e122c774603f49c54cf8d62b368f9c63f4233 Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Sun, 19 Sep 2021 14:47:20 -0500 Subject: [PATCH 01/10] add try_*, readable, writable, ready, and peer_addr methods to tcp and unix split halves Also adds a doc test to UnixStream::peer_addr(). --- tokio/src/net/tcp/split.rs | 627 ++++++++++++++++++++++++++++- tokio/src/net/tcp/split_owned.rs | 625 ++++++++++++++++++++++++++++- tokio/src/net/unix/split.rs | 647 +++++++++++++++++++++++++++++- tokio/src/net/unix/split_owned.rs | 643 ++++++++++++++++++++++++++++- tokio/src/net/unix/stream.rs | 15 + 5 files changed, 2551 insertions(+), 6 deletions(-) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index 8ae70ce13bc..b5f9f6a2274 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -9,14 +9,18 @@ //! level. use crate::future::poll_fn; -use crate::io::{AsyncRead, AsyncWrite, ReadBuf}; +use crate::io::{AsyncRead, AsyncWrite, Interest, ReadBuf, Ready}; use crate::net::TcpStream; use std::io; -use std::net::Shutdown; +use std::net::{Shutdown, SocketAddr}; use std::pin::Pin; use std::task::{Context, Poll}; +cfg_io_util! { + use bytes::BufMut; +} + /// Borrowed read half of a [`TcpStream`], created by [`split`]. /// /// Reading from a `ReadHalf` is usually done using the convenience methods found on the @@ -134,6 +138,625 @@ impl ReadHalf<'_> { let mut buf = ReadBuf::new(buf); poll_fn(|cx| self.poll_peek(cx, &mut buf)).await } + + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// This function is equivalent to [TcpStream::ready]. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, write_half) = stream.split(); + /// + /// loop { + /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.0.ready(interest).await + } + + /// Wait for the socket to become readable. + /// + /// This function is equivalent to `ready(Interest::READABLE)` and is usually + /// paired with `try_read()`. + /// This function is also equivalent to [TcpStream::ready]. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// // split stream + /// let (read_half, _write_half) = stream.split(); + /// + /// let mut msg = vec![0; 1024]; + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut msg) { + /// Ok(n) => { + /// msg.truncate(n); + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// println!("GOT = {:?}", msg); + /// Ok(()) + /// } + /// ``` + pub async fn readable(&self) -> io::Result<()> { + self.0.readable().await + } + + /// Try to read data from the stream into the provided buffer, returning how + /// many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, _write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf = [0; 4096]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read(&self, buf: &mut [u8]) -> io::Result { + self.0.try_read(buf) + } + + /// Try to read data from the stream into the provided buffers, returning + /// how many bytes were read. + /// + /// Data is copied to fill each buffer in order, with the final buffer + /// written to possibly being only partially filled. This method behaves + /// equivalently to a single call to [`try_read()`] with concatenated + /// buffers. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_vectored()` is non-blocking, the buffer does not have to be + /// stored by the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`try_read()`]: TcpStream::try_read() + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io::{self, IoSliceMut}; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf_a = [0; 512]; + /// let mut buf_b = [0; 1024]; + /// let mut bufs = [ + /// IoSliceMut::new(&mut buf_a), + /// IoSliceMut::new(&mut buf_b), + /// ]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_vectored(&mut bufs) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.0.try_read_vectored(bufs) + } + + cfg_io_util! { + /// Try to read data from the stream into the provided buffer, advancing the + /// buffer's internal cursor, returning how many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_buf()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, _write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// let mut buf = Vec::with_capacity(4096); + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_buf(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_buf(&self, buf: &mut B) -> io::Result { + self.0.try_read_buf(buf) + } + } + + /// Returns the remote address that this stream is connected to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (read_half, _write_half) = stream.split(); + /// + /// println!("{:?}", read_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.0.peer_addr() + } +} + +impl WriteHalf<'_> { + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// This function is equivalent to [TcpStream::ready]. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, write_half) = stream.split(); + /// + /// loop { + /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.0.ready(interest).await + } + + /// Wait for the socket to become writable. + /// + /// This function is equivalent to `ready(Interest::WRITABLE)` and is usually + /// paired with `try_write()`. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (_read_half, write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub async fn writable(&self) -> io::Result<()> { + self.0.writable().await + } + + /// Try to write a buffer to the stream, returning how many bytes were + /// written. + /// + /// The function will attempt to write the entire contents of `buf`, but + /// only part of the buffer may be written. + /// + /// This function is usually paired with `writable()`. + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (_read_half, write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write(&self, buf: &[u8]) -> io::Result { + self.0.try_write(buf) + } + + /// Try to write several buffers to the stream, returning how many bytes + /// were written. + /// + /// Data is written from each buffer in order, with the final buffer read + /// from possible being only partially consumed. This method behaves + /// equivalently to a single call to [`try_write()`] with concatenated + /// buffers. + /// + /// This function is usually paired with `writable()`. + /// + /// [`try_write()`]: TcpStream::try_write() + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (_read_half, write_half) = stream.split(); + /// + /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; + /// + /// loop { + /// // Wait for the socket to be writable + /// stream.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match stream.try_write_vectored(&bufs) { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write_vectored(&self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.0.try_write_vectored(bufs) + } + + /// Returns the remote address that this stream is connected to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (_read_half, write_half) = stream.split(); + /// + /// println!("{:?}", write_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.0.peer_addr() + } } impl AsyncRead for ReadHalf<'_> { diff --git a/tokio/src/net/tcp/split_owned.rs b/tokio/src/net/tcp/split_owned.rs index 1bcb4f2eafe..517f58caaed 100644 --- a/tokio/src/net/tcp/split_owned.rs +++ b/tokio/src/net/tcp/split_owned.rs @@ -9,16 +9,20 @@ //! level. use crate::future::poll_fn; -use crate::io::{AsyncRead, AsyncWrite, ReadBuf}; +use crate::io::{AsyncRead, AsyncWrite, Interest, ReadBuf, Ready}; use crate::net::TcpStream; use std::error::Error; -use std::net::Shutdown; +use std::net::{Shutdown, SocketAddr}; use std::pin::Pin; use std::sync::Arc; use std::task::{Context, Poll}; use std::{fmt, io}; +cfg_io_util! { + use bytes::BufMut; +} + /// Owned read half of a [`TcpStream`], created by [`into_split`]. /// /// Reading from an `OwnedReadHalf` is usually done using the convenience methods found @@ -189,6 +193,364 @@ impl OwnedReadHalf { let mut buf = ReadBuf::new(buf); poll_fn(|cx| self.poll_peek(cx, &mut buf)).await } + + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// This function is equivalent to [TcpStream::ready]. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, write_half) = stream.into_split(); + /// + /// loop { + /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.inner.ready(interest).await + } + + /// Wait for the socket to become readable. + /// + /// This function is equivalent to `ready(Interest::READABLE)` and is usually + /// paired with `try_read()`. + /// This function is also equivalent to [TcpStream::ready]. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// // split stream + /// let (read_half, _write_half) = stream.into_split(); + /// + /// let mut msg = vec![0; 1024]; + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut msg) { + /// Ok(n) => { + /// msg.truncate(n); + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// println!("GOT = {:?}", msg); + /// Ok(()) + /// } + /// ``` + pub async fn readable(&self) -> io::Result<()> { + self.inner.readable().await + } + + /// Try to read data from the stream into the provided buffer, returning how + /// many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf = [0; 4096]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read(&self, buf: &mut [u8]) -> io::Result { + self.inner.try_read(buf) + } + + /// Try to read data from the stream into the provided buffers, returning + /// how many bytes were read. + /// + /// Data is copied to fill each buffer in order, with the final buffer + /// written to possibly being only partially filled. This method behaves + /// equivalently to a single call to [`try_read()`] with concatenated + /// buffers. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_vectored()` is non-blocking, the buffer does not have to be + /// stored by the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`try_read()`]: TcpStream::try_read() + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io::{self, IoSliceMut}; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf_a = [0; 512]; + /// let mut buf_b = [0; 1024]; + /// let mut bufs = [ + /// IoSliceMut::new(&mut buf_a), + /// IoSliceMut::new(&mut buf_b), + /// ]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_vectored(&mut bufs) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.inner.try_read_vectored(bufs) + } + + cfg_io_util! { + /// Try to read data from the stream into the provided buffer, advancing the + /// buffer's internal cursor, returning how many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_buf()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: TcpStream::readable() + /// [`ready()`]: TcpStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// let mut buf = Vec::with_capacity(4096); + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_buf(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_buf(&self, buf: &mut B) -> io::Result { + self.inner.try_read_buf(buf) + } + } + + /// Returns the remote address that this stream is connected to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (read_half, _write_half) = stream.into_split(); + /// + /// println!("{:?}", read_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.inner.peer_addr() + } } impl AsyncRead for OwnedReadHalf { @@ -218,6 +580,265 @@ impl OwnedWriteHalf { self.shutdown_on_drop = false; drop(self); } + + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// This function is equivalent to [TcpStream::ready]. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (read_half, write_half) = stream.into_split(); + /// + /// loop { + /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.inner.ready(interest).await + } + + /// Wait for the socket to become writable. + /// + /// This function is equivalent to `ready(Interest::WRITABLE)` and is usually + /// paired with `try_write()`. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (_read_half, write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub async fn writable(&self) -> io::Result<()> { + self.inner.writable().await + } + + /// Try to write a buffer to the stream, returning how many bytes were + /// written. + /// + /// The function will attempt to write the entire contents of `buf`, but + /// only part of the buffer may be written. + /// + /// This function is usually paired with `writable()`. + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// + /// let (_read_half, write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write(&self, buf: &[u8]) -> io::Result { + self.inner.try_write(buf) + } + + /// Try to write several buffers to the stream, returning how many bytes + /// were written. + /// + /// Data is written from each buffer in order, with the final buffer read + /// from possible being only partially consumed. This method behaves + /// equivalently to a single call to [`try_write()`] with concatenated + /// buffers. + /// + /// This function is usually paired with `writable()`. + /// + /// [`try_write()`]: TcpStream::try_write() + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (_read_half, write_half) = stream.into_split(); + /// + /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write_vectored(&bufs) { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write_vectored(&self, bufs: &[io::IoSlice<'_>]) -> io::Result { + self.inner.try_write_vectored(bufs) + } + + /// Returns the remote address that this stream is connected to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (_read_half, write_half) = stream.into_split(); + /// + /// println!("{:?}", write_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.inner.peer_addr() + } } impl Drop for OwnedWriteHalf { diff --git a/tokio/src/net/unix/split.rs b/tokio/src/net/unix/split.rs index 97214f7a7cf..da48b5f6111 100644 --- a/tokio/src/net/unix/split.rs +++ b/tokio/src/net/unix/split.rs @@ -8,14 +8,19 @@ //! split has no associated overhead and enforces all invariants at the type //! level. -use crate::io::{AsyncRead, AsyncWrite, ReadBuf}; +use crate::io::{AsyncRead, AsyncWrite, Interest, ReadBuf, Ready}; use crate::net::UnixStream; +use crate::net::unix::SocketAddr; use std::io; use std::net::Shutdown; use std::pin::Pin; use std::task::{Context, Poll}; +cfg_io_util! { + use bytes::BufMut; +} + /// Borrowed read half of a [`UnixStream`], created by [`split`]. /// /// Reading from a `ReadHalf` is usually done using the convenience methods found on the @@ -47,6 +52,646 @@ pub(crate) fn split(stream: &mut UnixStream) -> (ReadHalf<'_>, WriteHalf<'_>) { (ReadHalf(stream), WriteHalf(stream)) } +impl ReadHalf<'_> { + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, write_half) = stream.split(); + /// + /// loop { + /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.0.ready(interest).await + } + + /// Wait for the socket to become readable. + /// + /// This function is equivalent to `ready(Interest::READABLE)` and is usually + /// paired with `try_read()`. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.split(); + /// + /// let mut msg = vec![0; 1024]; + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut msg) { + /// Ok(n) => { + /// msg.truncate(n); + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// println!("GOT = {:?}", msg); + /// Ok(()) + /// } + /// ``` + pub async fn readable(&self) -> io::Result<()> { + self.0.readable().await + } + + /// Try to read data from the stream into the provided buffer, returning how + /// many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: UnixStream::readable() + /// [`ready()`]: UnixStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf = [0; 4096]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read(&self, buf: &mut [u8]) -> io::Result { + self.0.try_read(buf) + } + + cfg_io_util! { + /// Try to read data from the stream into the provided buffer, advancing the + /// buffer's internal cursor, returning how many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_buf()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: UnixStream::readable() + /// [`ready()`]: UnixStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// let mut buf = Vec::with_capacity(4096); + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_buf(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_buf(&self, buf: &mut B) -> io::Result { + self.0.try_read_buf(buf) + } + } + + /// Try to read data from the stream into the provided buffers, returning + /// how many bytes were read. + /// + /// Data is copied to fill each buffer in order, with the final buffer + /// written to possibly being only partially filled. This method behaves + /// equivalently to a single call to [`try_read()`] with concatenated + /// buffers. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_vectored()` is non-blocking, the buffer does not have to be + /// stored by the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`try_read()`]: UnixStream::try_read() + /// [`readable()`]: UnixStream::readable() + /// [`ready()`]: UnixStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io::{self, IoSliceMut}; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf_a = [0; 512]; + /// let mut buf_b = [0; 1024]; + /// let mut bufs = [ + /// IoSliceMut::new(&mut buf_a), + /// IoSliceMut::new(&mut buf_b), + /// ]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_vectored(&mut bufs) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.0.try_read_vectored(bufs) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// println!("{:?}", read_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.0.peer_addr() + } +} + +impl WriteHalf<'_> { + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, write_half) = stream.split(); + /// + /// loop { + /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.0.ready(interest).await + } + + /// Wait for the socket to become writable. + /// + /// This function is equivalent to `ready(Interest::WRITABLE)` and is usually + /// paired with `try_write()`. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub async fn writable(&self) -> io::Result<()> { + self.0.writable().await + } + + /// Try to write a buffer to the stream, returning how many bytes were + /// written. + /// + /// The function will attempt to write the entire contents of `buf`, but + /// only part of the buffer may be written. + /// + /// This function is usually paired with `writable()`. + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write(&self, buf: &[u8]) -> io::Result { + self.0.try_write(buf) + } + + /// Try to write several buffers to the stream, returning how many bytes + /// were written. + /// + /// Data is written from each buffer in order, with the final buffer read + /// from possible being only partially consumed. This method behaves + /// equivalently to a single call to [`try_write()`] with concatenated + /// buffers. + /// + /// This function is usually paired with `writable()`. + /// + /// [`try_write()`]: UnixStream::try_write() + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.split(); + /// + /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write_vectored(&bufs) { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write_vectored(&self, buf: &[io::IoSlice<'_>]) -> io::Result { + self.0.try_write_vectored(buf) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.split(); + /// + /// println!("{:?}", write_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.0.peer_addr() + } +} + impl AsyncRead for ReadHalf<'_> { fn poll_read( self: Pin<&mut Self>, diff --git a/tokio/src/net/unix/split_owned.rs b/tokio/src/net/unix/split_owned.rs index 3d6ac6a7eb4..9e5b4c111cd 100644 --- a/tokio/src/net/unix/split_owned.rs +++ b/tokio/src/net/unix/split_owned.rs @@ -8,9 +8,10 @@ //! split has no associated overhead and enforces all invariants at the type //! level. -use crate::io::{AsyncRead, AsyncWrite, ReadBuf}; +use crate::io::{AsyncRead, AsyncWrite, Interest, ReadBuf, Ready}; use crate::net::UnixStream; +use crate::net::unix::SocketAddr; use std::error::Error; use std::net::Shutdown; use std::pin::Pin; @@ -18,6 +19,10 @@ use std::sync::Arc; use std::task::{Context, Poll}; use std::{fmt, io}; +cfg_io_util! { + use bytes::BufMut; +} + /// Owned read half of a [`UnixStream`], created by [`into_split`]. /// /// Reading from an `OwnedReadHalf` is usually done using the convenience methods found @@ -102,6 +107,373 @@ impl OwnedReadHalf { pub fn reunite(self, other: OwnedWriteHalf) -> Result { reunite(self, other) } + + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, write_half) = stream.into_split(); + /// + /// loop { + /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.inner.ready(interest).await + } + + /// Wait for the socket to become readable. + /// + /// This function is equivalent to `ready(Interest::READABLE)` and is usually + /// paired with `try_read()`. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// let mut msg = vec![0; 1024]; + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut msg) { + /// Ok(n) => { + /// msg.truncate(n); + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// println!("GOT = {:?}", msg); + /// Ok(()) + /// } + /// ``` + pub async fn readable(&self) -> io::Result<()> { + self.inner.readable().await + } + + /// Try to read data from the stream into the provided buffer, returning how + /// many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: UnixStream::readable() + /// [`ready()`]: UnixStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf = [0; 4096]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read(&self, buf: &mut [u8]) -> io::Result { + self.inner.try_read(buf) + } + + cfg_io_util! { + /// Try to read data from the stream into the provided buffer, advancing the + /// buffer's internal cursor, returning how many bytes were read. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_buf()` is non-blocking, the buffer does not have to be stored by + /// the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`readable()`]: UnixStream::readable() + /// [`ready()`]: UnixStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// let mut buf = Vec::with_capacity(4096); + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_buf(&mut buf) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_buf(&self, buf: &mut B) -> io::Result { + self.inner.try_read_buf(buf) + } + } + + /// Try to read data from the stream into the provided buffers, returning + /// how many bytes were read. + /// + /// Data is copied to fill each buffer in order, with the final buffer + /// written to possibly being only partially filled. This method behaves + /// equivalently to a single call to [`try_read()`] with concatenated + /// buffers. + /// + /// Receives any pending data from the socket but does not wait for new data + /// to arrive. On success, returns the number of bytes read. Because + /// `try_read_vectored()` is non-blocking, the buffer does not have to be + /// stored by the async task and can exist entirely on the stack. + /// + /// Usually, [`readable()`] or [`ready()`] is used with this function. + /// + /// [`try_read()`]: UnixStream::try_read() + /// [`readable()`]: UnixStream::readable() + /// [`ready()`]: UnixStream::ready() + /// + /// # Return + /// + /// If data is successfully read, `Ok(n)` is returned, where `n` is the + /// number of bytes read. `Ok(0)` indicates the stream's read half is closed + /// and will no longer yield data. If the stream is not ready to read data + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io::{self, IoSliceMut}; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be readable + /// read_half.readable().await?; + /// + /// // Creating the buffer **after** the `await` prevents it from + /// // being stored in the async task. + /// let mut buf_a = [0; 512]; + /// let mut buf_b = [0; 1024]; + /// let mut bufs = [ + /// IoSliceMut::new(&mut buf_a), + /// IoSliceMut::new(&mut buf_b), + /// ]; + /// + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read_vectored(&mut bufs) { + /// Ok(0) => break, + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { + self.inner.try_read_vectored(bufs) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, _write_half) = stream.into_split(); + /// + /// println!("{:?}", read_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.inner.peer_addr() + } } impl AsyncRead for OwnedReadHalf { @@ -131,6 +503,275 @@ impl OwnedWriteHalf { self.shutdown_on_drop = false; drop(self); } + + /// Wait for any of the requested ready states. + /// + /// This function is usually paired with `try_read()` or `try_write()`. It + /// can be used to concurrently read / write to the same socket on a single + /// task without splitting the socket. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to read or write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// Concurrently read and write to the stream on the same task without + /// splitting. + /// + /// ```no_run + /// use tokio::io::Interest; + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (read_half, write_half) = stream.into_split(); + /// + /// loop { + /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; + /// + /// if ready.is_readable() { + /// let mut data = vec![0; 1024]; + /// // Try to read data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match read_half.try_read(&mut data) { + /// Ok(n) => { + /// println!("read {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// + /// } + /// + /// if ready.is_writable() { + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// println!("write {} bytes", n); + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// } + /// } + /// ``` + pub async fn ready(&self, interest: Interest) -> io::Result { + self.inner.ready(interest).await + } + + /// Wait for the socket to become writable. + /// + /// This function is equivalent to `ready(Interest::WRITABLE)` and is usually + /// paired with `try_write()`. + /// + /// # Cancel safety + /// + /// This method is cancel safe. Once a readiness event occurs, the method + /// will continue to return immediately until the readiness event is + /// consumed by an attempt to write that fails with `WouldBlock` or + /// `Poll::Pending`. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub async fn writable(&self) -> io::Result<()> { + self.inner.writable().await + } + + /// Try to write a buffer to the stream, returning how many bytes were + /// written. + /// + /// The function will attempt to write the entire contents of `buf`, but + /// only part of the buffer may be written. + /// + /// This function is usually paired with `writable()`. + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.into_split(); + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write(b"hello world") { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write(&self, buf: &[u8]) -> io::Result { + self.inner.try_write(buf) + } + + /// Try to write several buffers to the stream, returning how many bytes + /// were written. + /// + /// Data is written from each buffer in order, with the final buffer read + /// from possible being only partially consumed. This method behaves + /// equivalently to a single call to [`try_write()`] with concatenated + /// buffers. + /// + /// This function is usually paired with `writable()`. + /// + /// [`try_write()`]: UnixStream::try_write() + /// + /// # Return + /// + /// If data is successfully written, `Ok(n)` is returned, where `n` is the + /// number of bytes written. If the stream is not ready to write data, + /// `Err(io::ErrorKind::WouldBlock)` is returned. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// use std::error::Error; + /// use std::io; + /// + /// #[tokio::main] + /// async fn main() -> Result<(), Box> { + /// // Connect to a peer + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.into_split(); + /// + /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; + /// + /// loop { + /// // Wait for the socket to be writable + /// write_half.writable().await?; + /// + /// // Try to write data, this may still fail with `WouldBlock` + /// // if the readiness event is a false positive. + /// match write_half.try_write_vectored(&bufs) { + /// Ok(n) => { + /// break; + /// } + /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { + /// continue; + /// } + /// Err(e) => { + /// return Err(e.into()); + /// } + /// } + /// } + /// + /// Ok(()) + /// } + /// ``` + pub fn try_write_vectored(&self, buf: &[io::IoSlice<'_>]) -> io::Result { + self.inner.try_write_vectored(buf) + } + + /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// let (_read_half, write_half) = stream.into_split(); + /// + /// println!("{:?}", write_half.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn peer_addr(&self) -> io::Result { + self.inner.peer_addr() + } } impl Drop for OwnedWriteHalf { diff --git a/tokio/src/net/unix/stream.rs b/tokio/src/net/unix/stream.rs index 5837f3673f8..8c801ce70b4 100644 --- a/tokio/src/net/unix/stream.rs +++ b/tokio/src/net/unix/stream.rs @@ -778,6 +778,21 @@ impl UnixStream { } /// Returns the socket address of the remote half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// println!("{:?}", stream.peer_addr()?); + /// # Ok(()) + /// # } + /// ``` pub fn peer_addr(&self) -> io::Result { self.io.peer_addr().map(SocketAddr) } From e429067ae94a93b6e5ccf74c86dc9c9f77cfeee9 Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Mon, 20 Sep 2021 11:22:34 -0500 Subject: [PATCH 02/10] fix documentation mistake in unix read half --- tokio/src/net/unix/split.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tokio/src/net/unix/split.rs b/tokio/src/net/unix/split.rs index da48b5f6111..d04e329d73e 100644 --- a/tokio/src/net/unix/split.rs +++ b/tokio/src/net/unix/split.rs @@ -408,9 +408,9 @@ impl ReadHalf<'_> { /// # async fn dox() -> Result<(), Box> { /// let dir = tempfile::tempdir().unwrap(); /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; + /// let mut stream = UnixStream::connect(bind_path).await?; /// - /// let (read_half, _write_half) = stream.into_split(); + /// let (read_half, _write_half) = stream.split(); /// /// println!("{:?}", read_half.peer_addr()?); /// # Ok(()) From e05e281a1cb93b6fb327d95c59d59c816987b657 Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Mon, 20 Sep 2021 11:24:46 -0500 Subject: [PATCH 03/10] add documentation example for unix stream local_addr method --- tokio/src/net/unix/stream.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tokio/src/net/unix/stream.rs b/tokio/src/net/unix/stream.rs index 8c801ce70b4..a4eec194bfb 100644 --- a/tokio/src/net/unix/stream.rs +++ b/tokio/src/net/unix/stream.rs @@ -773,6 +773,20 @@ impl UnixStream { } /// Returns the socket address of the local half of this connection. + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// + /// println!("{:?}", stream.local_addr()?); + /// # Ok(()) + /// # } + /// ``` pub fn local_addr(&self) -> io::Result { self.io.local_addr().map(SocketAddr) } From 2edf6fda537a37359a0ec6b18b3f2a4718d8c753 Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Mon, 20 Sep 2021 11:30:35 -0500 Subject: [PATCH 04/10] add local_addr to split halves of unix and tcp streams --- tokio/src/net/tcp/split.rs | 38 ++++++++++++++++++++++++++++ tokio/src/net/tcp/split_owned.rs | 38 ++++++++++++++++++++++++++++ tokio/src/net/unix/split.rs | 42 +++++++++++++++++++++++++++++++ tokio/src/net/unix/split_owned.rs | 42 +++++++++++++++++++++++++++++++ 4 files changed, 160 insertions(+) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index b5f9f6a2274..97ebae36c58 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -496,6 +496,25 @@ impl ReadHalf<'_> { pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } + + /// Returns the local address that this stream is bound to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (read_half, _write_half) = stream.split(); + /// + /// println!("{:?}", read_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.0.local_addr() + } } impl WriteHalf<'_> { @@ -757,6 +776,25 @@ impl WriteHalf<'_> { pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } + + /// Returns the local address that this stream is bound to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (_read_half, write_half) = stream.split(); + /// + /// println!("{:?}", write_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.0.local_addr() + } } impl AsyncRead for ReadHalf<'_> { diff --git a/tokio/src/net/tcp/split_owned.rs b/tokio/src/net/tcp/split_owned.rs index 517f58caaed..86dcd7d4d86 100644 --- a/tokio/src/net/tcp/split_owned.rs +++ b/tokio/src/net/tcp/split_owned.rs @@ -551,6 +551,25 @@ impl OwnedReadHalf { pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } + + /// Returns the local address that this stream is bound to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (read_half, _write_half) = stream.into_split(); + /// + /// println!("{:?}", read_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.inner.local_addr() + } } impl AsyncRead for OwnedReadHalf { @@ -839,6 +858,25 @@ impl OwnedWriteHalf { pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } + + /// Returns the local address that this stream is bound to. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::TcpStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let stream = TcpStream::connect("127.0.0.1:8080").await?; + /// let (_read_half, write_half) = stream.into_split(); + /// + /// println!("{:?}", write_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.inner.local_addr() + } } impl Drop for OwnedWriteHalf { diff --git a/tokio/src/net/unix/split.rs b/tokio/src/net/unix/split.rs index d04e329d73e..5b0514b3c91 100644 --- a/tokio/src/net/unix/split.rs +++ b/tokio/src/net/unix/split.rs @@ -419,6 +419,27 @@ impl ReadHalf<'_> { pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// let (read_half, _write_half) = stream.split(); + /// + /// println!("{:?}", read_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.0.local_addr() + } } impl WriteHalf<'_> { @@ -690,6 +711,27 @@ impl WriteHalf<'_> { pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let mut stream = UnixStream::connect(bind_path).await?; + /// let (_read_half, write_half) = stream.split(); + /// + /// println!("{:?}", write_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.0.local_addr() + } } impl AsyncRead for ReadHalf<'_> { diff --git a/tokio/src/net/unix/split_owned.rs b/tokio/src/net/unix/split_owned.rs index 9e5b4c111cd..d823faee46f 100644 --- a/tokio/src/net/unix/split_owned.rs +++ b/tokio/src/net/unix/split_owned.rs @@ -474,6 +474,27 @@ impl OwnedReadHalf { pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// let (read_half, _write_half) = stream.into_split(); + /// + /// println!("{:?}", read_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.inner.local_addr() + } } impl AsyncRead for OwnedReadHalf { @@ -772,6 +793,27 @@ impl OwnedWriteHalf { pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } + + /// Returns the socket address of the local half of this connection. + /// + /// # Examples + /// + /// ```no_run + /// use tokio::net::UnixStream; + /// + /// # async fn dox() -> Result<(), Box> { + /// let dir = tempfile::tempdir().unwrap(); + /// let bind_path = dir.path().join("bind_path"); + /// let stream = UnixStream::connect(bind_path).await?; + /// let (_read_half, write_half) = stream.into_split(); + /// + /// println!("{:?}", write_half.local_addr()?); + /// # Ok(()) + /// # } + /// ``` + pub fn local_addr(&self) -> io::Result { + self.inner.local_addr() + } } impl Drop for OwnedWriteHalf { From e7579c112abd370f00e07cfe8aef2e9e5c8bce68 Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Mon, 20 Sep 2021 12:29:15 -0500 Subject: [PATCH 05/10] add blank line to docs for unix stream local addr method --- tokio/src/net/unix/stream.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tokio/src/net/unix/stream.rs b/tokio/src/net/unix/stream.rs index a4eec194bfb..75e6f37af49 100644 --- a/tokio/src/net/unix/stream.rs +++ b/tokio/src/net/unix/stream.rs @@ -773,6 +773,7 @@ impl UnixStream { } /// Returns the socket address of the local half of this connection. + /// /// # Examples /// /// ```no_run From 01932c1d33156154fd1b4d5648600b300f2d873a Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Mon, 20 Sep 2021 18:24:49 -0500 Subject: [PATCH 06/10] remove doc examples from split half methods --- tokio/src/net/tcp/split.rs | 453 ---------------------------- tokio/src/net/tcp/split_owned.rs | 453 ---------------------------- tokio/src/net/unix/split.rs | 482 ------------------------------ tokio/src/net/unix/split_owned.rs | 481 ----------------------------- 4 files changed, 1869 deletions(-) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index 97ebae36c58..7ab5f88019c 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -153,63 +153,6 @@ impl ReadHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, write_half) = stream.split(); - /// - /// loop { - /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.0.ready(interest).await } @@ -226,48 +169,6 @@ impl ReadHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// // split stream - /// let (read_half, _write_half) = stream.split(); - /// - /// let mut msg = vec![0; 1024]; - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut msg) { - /// Ok(n) => { - /// msg.truncate(n); - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// println!("GOT = {:?}", msg); - /// Ok(()) - /// } - /// ``` pub async fn readable(&self) -> io::Result<()> { self.0.readable().await } @@ -291,48 +192,6 @@ impl ReadHalf<'_> { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf = [0; 4096]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read(&self, buf: &mut [u8]) -> io::Result { self.0.try_read(buf) } @@ -362,53 +221,6 @@ impl ReadHalf<'_> { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io::{self, IoSliceMut}; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf_a = [0; 512]; - /// let mut buf_b = [0; 1024]; - /// let mut bufs = [ - /// IoSliceMut::new(&mut buf_a), - /// IoSliceMut::new(&mut buf_b), - /// ]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_vectored(&mut bufs) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { self.0.try_read_vectored(bufs) } @@ -433,85 +245,17 @@ impl ReadHalf<'_> { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// let mut buf = Vec::with_capacity(4096); - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_buf(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_buf(&self, buf: &mut B) -> io::Result { self.0.try_read_buf(buf) } } /// Returns the remote address that this stream is connected to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (read_half, _write_half) = stream.split(); - /// - /// println!("{:?}", read_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Returns the local address that this stream is bound to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (read_half, _write_half) = stream.split(); - /// - /// println!("{:?}", read_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.0.local_addr() } @@ -532,63 +276,6 @@ impl WriteHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, write_half) = stream.split(); - /// - /// loop { - /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.0.ready(interest).await } @@ -604,43 +291,6 @@ impl WriteHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (_read_half, write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub async fn writable(&self) -> io::Result<()> { self.0.writable().await } @@ -658,43 +308,6 @@ impl WriteHalf<'_> { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (_read_half, write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write(&self, buf: &[u8]) -> io::Result { self.0.try_write(buf) } @@ -716,82 +329,16 @@ impl WriteHalf<'_> { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (_read_half, write_half) = stream.split(); - /// - /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; - /// - /// loop { - /// // Wait for the socket to be writable - /// stream.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match stream.try_write_vectored(&bufs) { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write_vectored(&self, bufs: &[io::IoSlice<'_>]) -> io::Result { self.0.try_write_vectored(bufs) } /// Returns the remote address that this stream is connected to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (_read_half, write_half) = stream.split(); - /// - /// println!("{:?}", write_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Returns the local address that this stream is bound to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (_read_half, write_half) = stream.split(); - /// - /// println!("{:?}", write_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.0.local_addr() } diff --git a/tokio/src/net/tcp/split_owned.rs b/tokio/src/net/tcp/split_owned.rs index 86dcd7d4d86..8fecc975c7d 100644 --- a/tokio/src/net/tcp/split_owned.rs +++ b/tokio/src/net/tcp/split_owned.rs @@ -208,63 +208,6 @@ impl OwnedReadHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, write_half) = stream.into_split(); - /// - /// loop { - /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.inner.ready(interest).await } @@ -281,48 +224,6 @@ impl OwnedReadHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// // split stream - /// let (read_half, _write_half) = stream.into_split(); - /// - /// let mut msg = vec![0; 1024]; - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut msg) { - /// Ok(n) => { - /// msg.truncate(n); - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// println!("GOT = {:?}", msg); - /// Ok(()) - /// } - /// ``` pub async fn readable(&self) -> io::Result<()> { self.inner.readable().await } @@ -346,48 +247,6 @@ impl OwnedReadHalf { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf = [0; 4096]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read(&self, buf: &mut [u8]) -> io::Result { self.inner.try_read(buf) } @@ -417,53 +276,6 @@ impl OwnedReadHalf { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io::{self, IoSliceMut}; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let mut stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf_a = [0; 512]; - /// let mut buf_b = [0; 1024]; - /// let mut bufs = [ - /// IoSliceMut::new(&mut buf_a), - /// IoSliceMut::new(&mut buf_b), - /// ]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_vectored(&mut bufs) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { self.inner.try_read_vectored(bufs) } @@ -488,85 +300,17 @@ impl OwnedReadHalf { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// let mut buf = Vec::with_capacity(4096); - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_buf(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_buf(&self, buf: &mut B) -> io::Result { self.inner.try_read_buf(buf) } } /// Returns the remote address that this stream is connected to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (read_half, _write_half) = stream.into_split(); - /// - /// println!("{:?}", read_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } /// Returns the local address that this stream is bound to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (read_half, _write_half) = stream.into_split(); - /// - /// println!("{:?}", read_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.inner.local_addr() } @@ -614,63 +358,6 @@ impl OwnedWriteHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (read_half, write_half) = stream.into_split(); - /// - /// loop { - /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.inner.ready(interest).await } @@ -686,43 +373,6 @@ impl OwnedWriteHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (_read_half, write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub async fn writable(&self) -> io::Result<()> { self.inner.writable().await } @@ -740,43 +390,6 @@ impl OwnedWriteHalf { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// - /// let (_read_half, write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write(&self, buf: &[u8]) -> io::Result { self.inner.try_write(buf) } @@ -798,82 +411,16 @@ impl OwnedWriteHalf { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (_read_half, write_half) = stream.into_split(); - /// - /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write_vectored(&bufs) { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write_vectored(&self, bufs: &[io::IoSlice<'_>]) -> io::Result { self.inner.try_write_vectored(bufs) } /// Returns the remote address that this stream is connected to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (_read_half, write_half) = stream.into_split(); - /// - /// println!("{:?}", write_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } /// Returns the local address that this stream is bound to. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::TcpStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let stream = TcpStream::connect("127.0.0.1:8080").await?; - /// let (_read_half, write_half) = stream.into_split(); - /// - /// println!("{:?}", write_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.inner.local_addr() } diff --git a/tokio/src/net/unix/split.rs b/tokio/src/net/unix/split.rs index 5b0514b3c91..48e09bb137c 100644 --- a/tokio/src/net/unix/split.rs +++ b/tokio/src/net/unix/split.rs @@ -65,65 +65,6 @@ impl ReadHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, write_half) = stream.split(); - /// - /// loop { - /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.0.ready(interest).await } @@ -139,49 +80,6 @@ impl ReadHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// let mut msg = vec![0; 1024]; - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut msg) { - /// Ok(n) => { - /// msg.truncate(n); - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// println!("GOT = {:?}", msg); - /// Ok(()) - /// } - /// ``` pub async fn readable(&self) -> io::Result<()> { self.0.readable().await } @@ -205,50 +103,6 @@ impl ReadHalf<'_> { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf = [0; 4096]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read(&self, buf: &mut [u8]) -> io::Result { self.0.try_read(buf) } @@ -272,49 +126,6 @@ impl ReadHalf<'_> { /// If data is successfully read, `Ok(n)` is returned, where `n` is the /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data - /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// let mut buf = Vec::with_capacity(4096); - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_buf(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_buf(&self, buf: &mut B) -> io::Result { self.0.try_read_buf(buf) } @@ -345,98 +156,16 @@ impl ReadHalf<'_> { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io::{self, IoSliceMut}; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf_a = [0; 512]; - /// let mut buf_b = [0; 1024]; - /// let mut bufs = [ - /// IoSliceMut::new(&mut buf_a), - /// IoSliceMut::new(&mut buf_b), - /// ]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_vectored(&mut bufs) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { self.0.try_read_vectored(bufs) } /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.split(); - /// - /// println!("{:?}", read_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// let (read_half, _write_half) = stream.split(); - /// - /// println!("{:?}", read_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.0.local_addr() } @@ -455,65 +184,6 @@ impl WriteHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, write_half) = stream.split(); - /// - /// loop { - /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.0.ready(interest).await } @@ -529,45 +199,6 @@ impl WriteHalf<'_> { /// will continue to return immediately until the readiness event is /// consumed by an attempt to write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub async fn writable(&self) -> io::Result<()> { self.0.writable().await } @@ -585,45 +216,6 @@ impl WriteHalf<'_> { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write(&self, buf: &[u8]) -> io::Result { self.0.try_write(buf) } @@ -645,90 +237,16 @@ impl WriteHalf<'_> { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.split(); - /// - /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write_vectored(&bufs) { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write_vectored(&self, buf: &[io::IoSlice<'_>]) -> io::Result { self.0.try_write_vectored(buf) } /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.split(); - /// - /// println!("{:?}", write_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.0.peer_addr() } /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let mut stream = UnixStream::connect(bind_path).await?; - /// let (_read_half, write_half) = stream.split(); - /// - /// println!("{:?}", write_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.0.local_addr() } diff --git a/tokio/src/net/unix/split_owned.rs b/tokio/src/net/unix/split_owned.rs index d823faee46f..613a01f36e5 100644 --- a/tokio/src/net/unix/split_owned.rs +++ b/tokio/src/net/unix/split_owned.rs @@ -120,65 +120,6 @@ impl OwnedReadHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, write_half) = stream.into_split(); - /// - /// loop { - /// let ready = read_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.inner.ready(interest).await } @@ -194,49 +135,6 @@ impl OwnedReadHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// let mut msg = vec![0; 1024]; - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut msg) { - /// Ok(n) => { - /// msg.truncate(n); - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// println!("GOT = {:?}", msg); - /// Ok(()) - /// } - /// ``` pub async fn readable(&self) -> io::Result<()> { self.inner.readable().await } @@ -260,50 +158,6 @@ impl OwnedReadHalf { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf = [0; 4096]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read(&self, buf: &mut [u8]) -> io::Result { self.inner.try_read(buf) } @@ -328,48 +182,6 @@ impl OwnedReadHalf { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// let mut buf = Vec::with_capacity(4096); - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_buf(&mut buf) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_buf(&self, buf: &mut B) -> io::Result { self.inner.try_read_buf(buf) } @@ -400,98 +212,16 @@ impl OwnedReadHalf { /// number of bytes read. `Ok(0)` indicates the stream's read half is closed /// and will no longer yield data. If the stream is not ready to read data /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io::{self, IoSliceMut}; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be readable - /// read_half.readable().await?; - /// - /// // Creating the buffer **after** the `await` prevents it from - /// // being stored in the async task. - /// let mut buf_a = [0; 512]; - /// let mut buf_b = [0; 1024]; - /// let mut bufs = [ - /// IoSliceMut::new(&mut buf_a), - /// IoSliceMut::new(&mut buf_b), - /// ]; - /// - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read_vectored(&mut bufs) { - /// Ok(0) => break, - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_read_vectored(&self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result { self.inner.try_read_vectored(bufs) } /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, _write_half) = stream.into_split(); - /// - /// println!("{:?}", read_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// let (read_half, _write_half) = stream.into_split(); - /// - /// println!("{:?}", read_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.inner.local_addr() } @@ -537,65 +267,6 @@ impl OwnedWriteHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to read or write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// Concurrently read and write to the stream on the same task without - /// splitting. - /// - /// ```no_run - /// use tokio::io::Interest; - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (read_half, write_half) = stream.into_split(); - /// - /// loop { - /// let ready = write_half.ready(Interest::READABLE | Interest::WRITABLE).await?; - /// - /// if ready.is_readable() { - /// let mut data = vec![0; 1024]; - /// // Try to read data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match read_half.try_read(&mut data) { - /// Ok(n) => { - /// println!("read {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// - /// } - /// - /// if ready.is_writable() { - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// println!("write {} bytes", n); - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// } - /// } - /// ``` pub async fn ready(&self, interest: Interest) -> io::Result { self.inner.ready(interest).await } @@ -611,45 +282,6 @@ impl OwnedWriteHalf { /// will continue to return immediately until the readiness event is /// consumed by an attempt to write that fails with `WouldBlock` or /// `Poll::Pending`. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub async fn writable(&self) -> io::Result<()> { self.inner.writable().await } @@ -667,45 +299,6 @@ impl OwnedWriteHalf { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.into_split(); - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write(b"hello world") { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write(&self, buf: &[u8]) -> io::Result { self.inner.try_write(buf) } @@ -727,90 +320,16 @@ impl OwnedWriteHalf { /// If data is successfully written, `Ok(n)` is returned, where `n` is the /// number of bytes written. If the stream is not ready to write data, /// `Err(io::ErrorKind::WouldBlock)` is returned. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// use std::error::Error; - /// use std::io; - /// - /// #[tokio::main] - /// async fn main() -> Result<(), Box> { - /// // Connect to a peer - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.into_split(); - /// - /// let bufs = [io::IoSlice::new(b"hello "), io::IoSlice::new(b"world")]; - /// - /// loop { - /// // Wait for the socket to be writable - /// write_half.writable().await?; - /// - /// // Try to write data, this may still fail with `WouldBlock` - /// // if the readiness event is a false positive. - /// match write_half.try_write_vectored(&bufs) { - /// Ok(n) => { - /// break; - /// } - /// Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => { - /// continue; - /// } - /// Err(e) => { - /// return Err(e.into()); - /// } - /// } - /// } - /// - /// Ok(()) - /// } - /// ``` pub fn try_write_vectored(&self, buf: &[io::IoSlice<'_>]) -> io::Result { self.inner.try_write_vectored(buf) } /// Returns the socket address of the remote half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// - /// let (_read_half, write_half) = stream.into_split(); - /// - /// println!("{:?}", write_half.peer_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn peer_addr(&self) -> io::Result { self.inner.peer_addr() } /// Returns the socket address of the local half of this connection. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::net::UnixStream; - /// - /// # async fn dox() -> Result<(), Box> { - /// let dir = tempfile::tempdir().unwrap(); - /// let bind_path = dir.path().join("bind_path"); - /// let stream = UnixStream::connect(bind_path).await?; - /// let (_read_half, write_half) = stream.into_split(); - /// - /// println!("{:?}", write_half.local_addr()?); - /// # Ok(()) - /// # } - /// ``` pub fn local_addr(&self) -> io::Result { self.inner.local_addr() } From ec1652019c4b64a6c5d6ef8fa676d713e7305c6c Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Sat, 25 Sep 2021 10:20:22 -0500 Subject: [PATCH 07/10] add backticks to doc comment Co-authored-by: Alice Ryhl --- tokio/src/net/tcp/split.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index 7ab5f88019c..3ccefe2a023 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -145,7 +145,7 @@ impl ReadHalf<'_> { /// can be used to concurrently read / write to the same socket on a single /// task without splitting the socket. /// - /// This function is equivalent to [TcpStream::ready]. + /// This function is equivalent to [`TcpStream::ready`]. /// /// # Cancel safety /// From 0fb6bd71788a5cdcd7d8ebbb787433dd514f7769 Mon Sep 17 00:00:00 2001 From: noah Date: Sat, 25 Sep 2021 10:33:44 -0500 Subject: [PATCH 08/10] fix documentation inconsistencies --- tokio/src/net/tcp/split.rs | 17 +++++++++-------- tokio/src/net/tcp/split_owned.rs | 17 +++++++++-------- tokio/src/net/unix/split.rs | 16 ++++++++-------- tokio/src/net/unix/split_owned.rs | 16 ++++++++-------- 4 files changed, 34 insertions(+), 32 deletions(-) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index 3ccefe2a023..6f49cbab795 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -161,6 +161,7 @@ impl ReadHalf<'_> { /// /// This function is equivalent to `ready(Interest::READABLE)` and is usually /// paired with `try_read()`. + /// /// This function is also equivalent to [TcpStream::ready]. /// /// # Cancel safety @@ -183,8 +184,8 @@ impl ReadHalf<'_> { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: TcpStream::readable() - /// [`ready()`]: TcpStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -211,9 +212,9 @@ impl ReadHalf<'_> { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`try_read()`]: TcpStream::try_read() - /// [`readable()`]: TcpStream::readable() - /// [`ready()`]: TcpStream::ready() + /// [`try_read()`]: Self::try_read() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -236,8 +237,8 @@ impl ReadHalf<'_> { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: TcpStream::readable() - /// [`ready()`]: TcpStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -322,7 +323,7 @@ impl WriteHalf<'_> { /// /// This function is usually paired with `writable()`. /// - /// [`try_write()`]: TcpStream::try_write() + /// [`try_write()`]: Self::try_write() /// /// # Return /// diff --git a/tokio/src/net/tcp/split_owned.rs b/tokio/src/net/tcp/split_owned.rs index 8fecc975c7d..a6553f071f6 100644 --- a/tokio/src/net/tcp/split_owned.rs +++ b/tokio/src/net/tcp/split_owned.rs @@ -216,6 +216,7 @@ impl OwnedReadHalf { /// /// This function is equivalent to `ready(Interest::READABLE)` and is usually /// paired with `try_read()`. + /// /// This function is also equivalent to [TcpStream::ready]. /// /// # Cancel safety @@ -238,8 +239,8 @@ impl OwnedReadHalf { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: TcpStream::readable() - /// [`ready()`]: TcpStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -266,9 +267,9 @@ impl OwnedReadHalf { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`try_read()`]: TcpStream::try_read() - /// [`readable()`]: TcpStream::readable() - /// [`ready()`]: TcpStream::ready() + /// [`try_read()`]: Self::try_read() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -291,8 +292,8 @@ impl OwnedReadHalf { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: TcpStream::readable() - /// [`ready()`]: TcpStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -404,7 +405,7 @@ impl OwnedWriteHalf { /// /// This function is usually paired with `writable()`. /// - /// [`try_write()`]: TcpStream::try_write() + /// [`try_write()`]: Self::try_write() /// /// # Return /// diff --git a/tokio/src/net/unix/split.rs b/tokio/src/net/unix/split.rs index 48e09bb137c..7dc47280824 100644 --- a/tokio/src/net/unix/split.rs +++ b/tokio/src/net/unix/split.rs @@ -94,8 +94,8 @@ impl ReadHalf<'_> { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: UnixStream::readable() - /// [`ready()`]: UnixStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -118,8 +118,8 @@ impl ReadHalf<'_> { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: UnixStream::readable() - /// [`ready()`]: UnixStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -146,9 +146,9 @@ impl ReadHalf<'_> { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`try_read()`]: UnixStream::try_read() - /// [`readable()`]: UnixStream::readable() - /// [`ready()`]: UnixStream::ready() + /// [`try_read()`]: Self::try_read() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -230,7 +230,7 @@ impl WriteHalf<'_> { /// /// This function is usually paired with `writable()`. /// - /// [`try_write()`]: UnixStream::try_write() + /// [`try_write()`]: Self::try_write() /// /// # Return /// diff --git a/tokio/src/net/unix/split_owned.rs b/tokio/src/net/unix/split_owned.rs index 613a01f36e5..47380b522e9 100644 --- a/tokio/src/net/unix/split_owned.rs +++ b/tokio/src/net/unix/split_owned.rs @@ -149,8 +149,8 @@ impl OwnedReadHalf { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: UnixStream::readable() - /// [`ready()`]: UnixStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -173,8 +173,8 @@ impl OwnedReadHalf { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`readable()`]: UnixStream::readable() - /// [`ready()`]: UnixStream::ready() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -202,9 +202,9 @@ impl OwnedReadHalf { /// /// Usually, [`readable()`] or [`ready()`] is used with this function. /// - /// [`try_read()`]: UnixStream::try_read() - /// [`readable()`]: UnixStream::readable() - /// [`ready()`]: UnixStream::ready() + /// [`try_read()`]: Self::try_read() + /// [`readable()`]: Self::readable() + /// [`ready()`]: Self::ready() /// /// # Return /// @@ -313,7 +313,7 @@ impl OwnedWriteHalf { /// /// This function is usually paired with `writable()`. /// - /// [`try_write()`]: UnixStream::try_write() + /// [`try_write()`]: Self::try_write() /// /// # Return /// From 90b2e6d92d1b65c6b575602fb8ae79fa6ee1b71a Mon Sep 17 00:00:00 2001 From: Noah Kennedy Date: Sat, 25 Sep 2021 11:09:36 -0500 Subject: [PATCH 09/10] add backticks to doc comment Co-authored-by: Alice Ryhl --- tokio/src/net/tcp/split.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index 6f49cbab795..56d72a5ff3b 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -162,7 +162,7 @@ impl ReadHalf<'_> { /// This function is equivalent to `ready(Interest::READABLE)` and is usually /// paired with `try_read()`. /// - /// This function is also equivalent to [TcpStream::ready]. + /// This function is also equivalent to [`TcpStream::ready`]. /// /// # Cancel safety /// From c9d280ee36e53950e64f311d920694abbfba6572 Mon Sep 17 00:00:00 2001 From: noah Date: Sat, 25 Sep 2021 11:17:34 -0500 Subject: [PATCH 10/10] add backticks to docs --- tokio/src/net/tcp/split.rs | 4 ++-- tokio/src/net/tcp/split_owned.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tokio/src/net/tcp/split.rs b/tokio/src/net/tcp/split.rs index 6f49cbab795..437ee19ea86 100644 --- a/tokio/src/net/tcp/split.rs +++ b/tokio/src/net/tcp/split.rs @@ -162,7 +162,7 @@ impl ReadHalf<'_> { /// This function is equivalent to `ready(Interest::READABLE)` and is usually /// paired with `try_read()`. /// - /// This function is also equivalent to [TcpStream::ready]. + /// This function is also equivalent to [`TcpStream::ready`]. /// /// # Cancel safety /// @@ -269,7 +269,7 @@ impl WriteHalf<'_> { /// can be used to concurrently read / write to the same socket on a single /// task without splitting the socket. /// - /// This function is equivalent to [TcpStream::ready]. + /// This function is equivalent to [`TcpStream::ready`]. /// /// # Cancel safety /// diff --git a/tokio/src/net/tcp/split_owned.rs b/tokio/src/net/tcp/split_owned.rs index a6553f071f6..7485fffe451 100644 --- a/tokio/src/net/tcp/split_owned.rs +++ b/tokio/src/net/tcp/split_owned.rs @@ -200,7 +200,7 @@ impl OwnedReadHalf { /// can be used to concurrently read / write to the same socket on a single /// task without splitting the socket. /// - /// This function is equivalent to [TcpStream::ready]. + /// This function is equivalent to [`TcpStream::ready`]. /// /// # Cancel safety /// @@ -217,7 +217,7 @@ impl OwnedReadHalf { /// This function is equivalent to `ready(Interest::READABLE)` and is usually /// paired with `try_read()`. /// - /// This function is also equivalent to [TcpStream::ready]. + /// This function is also equivalent to [`TcpStream::ready`]. /// /// # Cancel safety /// @@ -351,7 +351,7 @@ impl OwnedWriteHalf { /// can be used to concurrently read / write to the same socket on a single /// task without splitting the socket. /// - /// This function is equivalent to [TcpStream::ready]. + /// This function is equivalent to [`TcpStream::ready`]. /// /// # Cancel safety ///