From dff4ecd0e7102b0d72b76c191e1dd0a73b2d3a0e Mon Sep 17 00:00:00 2001 From: Michael Macias Date: Sun, 30 Jun 2024 20:50:49 -0500 Subject: [PATCH] io: implement `AsyncSeek` for `Empty` (#6663) * io: implement `AsyncSeek` for `Empty` * io: add more tests for seeking `Empty` This adds more tests seeking with other kinds of `SeekFrom`. It follows the same structure as used in rust-lang/rust@f1cd17961ccaac4bfaeeab81969cf36c56eec4a5. See . * io: add inline attribute to `AsyncSeek` implementations This follows the style of the other trait implementations of `Empty`. See . --------- Co-authored-by: Weijia Jiang --- tokio/src/io/util/empty.rs | 18 ++++++++++++++++-- tokio/tests/io_util_empty.rs | 31 ++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/tokio/src/io/util/empty.rs b/tokio/src/io/util/empty.rs index 289725ce49f..cc86e8b09a1 100644 --- a/tokio/src/io/util/empty.rs +++ b/tokio/src/io/util/empty.rs @@ -1,8 +1,8 @@ use crate::io::util::poll_proceed_and_make_progress; -use crate::io::{AsyncBufRead, AsyncRead, AsyncWrite, ReadBuf}; +use crate::io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite, ReadBuf}; use std::fmt; -use std::io; +use std::io::{self, SeekFrom}; use std::pin::Pin; use std::task::{Context, Poll}; @@ -133,6 +133,20 @@ impl AsyncWrite for Empty { } } +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 { .. }") diff --git a/tokio/tests/io_util_empty.rs b/tokio/tests/io_util_empty.rs index e49cd17fcd5..7a4b8c6a575 100644 --- a/tokio/tests/io_util_empty.rs +++ b/tokio/tests/io_util_empty.rs @@ -1,5 +1,5 @@ #![cfg(feature = "full")] -use tokio::io::{AsyncBufReadExt, AsyncReadExt}; +use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncSeekExt}; #[tokio::test] async fn empty_read_is_cooperative() { @@ -30,3 +30,32 @@ async fn empty_buf_reads_are_cooperative() { _ = tokio::task::yield_now() => {} } } + +#[tokio::test] +async fn empty_seek() { + use std::io::SeekFrom; + + let mut empty = tokio::io::empty(); + + assert!(matches!(empty.seek(SeekFrom::Start(0)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::Start(1)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::Start(u64::MAX)).await, Ok(0))); + + assert!(matches!(empty.seek(SeekFrom::End(i64::MIN)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::End(-1)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::End(0)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::End(1)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::End(i64::MAX)).await, Ok(0))); + + assert!(matches!( + empty.seek(SeekFrom::Current(i64::MIN)).await, + Ok(0) + )); + assert!(matches!(empty.seek(SeekFrom::Current(-1)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::Current(0)).await, Ok(0))); + assert!(matches!(empty.seek(SeekFrom::Current(1)).await, Ok(0))); + assert!(matches!( + empty.seek(SeekFrom::Current(i64::MAX)).await, + Ok(0) + )); +}