use crate::io::util::poll_proceed_and_make_progress; use crate::io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, ReadBuf}; use std::fmt; use std::io::{self, SeekFrom}; use std::pin::Pin; use std::task::{ready, Context, Poll}; cfg_io_util! { /// `Empty` ignores any data written via [`AsyncWrite`], and will always be empty /// (returning zero bytes) when read via [`AsyncRead`]. /// /// This struct is generally created by calling [`empty`]. Please see /// the documentation of [`empty()`][`empty`] for more details. /// /// This is an asynchronous version of [`std::io::empty`][std]. /// /// [`empty`]: fn@empty /// [std]: std::io::empty pub struct Empty { _p: (), } /// Creates a value that is always at EOF for reads, and ignores all data written. /// /// All writes on the returned instance will return `Poll::Ready(Ok(buf.len()))` /// and the contents of the buffer will not be inspected. /// /// All reads from the returned instance will return `Poll::Ready(Ok(0))`. /// /// This is an asynchronous version of [`std::io::empty`][std]. /// /// [std]: std::io::empty /// /// # Examples /// /// A slightly sad example of not reading anything into a buffer: /// /// ``` /// use tokio::io::{self, AsyncReadExt}; /// /// #[tokio::main] /// async fn main() { /// let mut buffer = String::new(); /// io::empty().read_to_string(&mut buffer).await.unwrap(); /// assert!(buffer.is_empty()); /// } /// ``` /// /// A convoluted way of getting the length of a buffer: /// /// ``` /// use tokio::io::{self, AsyncWriteExt}; /// /// #[tokio::main] /// async fn main() { /// let buffer = vec![1, 2, 3, 5, 8]; /// let num_bytes = io::empty().write(&buffer).await.unwrap(); /// assert_eq!(num_bytes, 5); /// } /// ``` pub fn empty() -> Empty { Empty { _p: () } } } impl AsyncRead for Empty { #[inline] fn poll_read( self: Pin<&mut Self>, cx: &mut Context<'_>, _: &mut ReadBuf<'_>, ) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); Poll::Ready(Ok(())) } } impl AsyncBufRead for Empty { #[inline] fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); Poll::Ready(Ok(&[])) } #[inline] fn consume(self: Pin<&mut Self>, _: usize) {} } impl AsyncWrite for Empty { #[inline] fn poll_write( self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); Poll::Ready(Ok(buf.len())) } #[inline] fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); Poll::Ready(Ok(())) } #[inline] fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); Poll::Ready(Ok(())) } #[inline] fn is_write_vectored(&self) -> bool { true } #[inline] fn poll_write_vectored( self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[io::IoSlice<'_>], ) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); let num_bytes = bufs.iter().map(|b| b.len()).sum(); Poll::Ready(Ok(num_bytes)) } } impl AsyncSeek for Empty { #[inline] fn start_seek(self: Pin<&mut Self>, _position: SeekFrom) -> io::Result<()> { Ok(()) } #[inline] fn poll_complete(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { ready!(crate::trace::trace_leaf(cx)); ready!(poll_proceed_and_make_progress(cx)); Poll::Ready(Ok(0)) } } impl fmt::Debug for Empty { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.pad("Empty { .. }") } } #[cfg(test)] mod tests { use super::*; #[test] fn assert_unpin() { crate::is_unpin::(); } }