From b0909583e1b555602e23ee6f185996178ac6aa69 Mon Sep 17 00:00:00 2001 From: Michael Macias Date: Thu, 27 Jun 2024 11:42:07 -0500 Subject: [PATCH 1/3] io: implement `AsyncSeek` for `Empty` --- tokio/src/io/util/empty.rs | 16 ++++++++++++++-- tokio/tests/io_util_empty.rs | 16 +++++++++++++++- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/tokio/src/io/util/empty.rs b/tokio/src/io/util/empty.rs index 289725ce49f..372440f80e2 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,18 @@ impl AsyncWrite for Empty { } } +impl AsyncSeek for Empty { + fn start_seek(self: Pin<&mut Self>, _position: SeekFrom) -> io::Result<()> { + Ok(()) + } + + 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..a6a1c507f3e 100644 --- a/tokio/tests/io_util_empty.rs +++ b/tokio/tests/io_util_empty.rs @@ -1,5 +1,6 @@ #![cfg(feature = "full")] -use tokio::io::{AsyncBufReadExt, AsyncReadExt}; +use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncSeekExt}; +use tokio_test::assert_ok; #[tokio::test] async fn empty_read_is_cooperative() { @@ -30,3 +31,16 @@ 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(); + + let pos = assert_ok!(empty.seek(SeekFrom::Start(0)).await); + assert_eq!(pos, 0); + + let pos = assert_ok!(empty.seek(SeekFrom::Start(8)).await); + assert_eq!(pos, 0); +} From efd2c0a8258da7219b0b3539f55ebfdab94a8b70 Mon Sep 17 00:00:00 2001 From: Michael Macias Date: Sun, 30 Jun 2024 14:02:32 -0500 Subject: [PATCH 2/3] 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 . --- tokio/tests/io_util_empty.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tokio/tests/io_util_empty.rs b/tokio/tests/io_util_empty.rs index a6a1c507f3e..7a4b8c6a575 100644 --- a/tokio/tests/io_util_empty.rs +++ b/tokio/tests/io_util_empty.rs @@ -1,6 +1,5 @@ #![cfg(feature = "full")] use tokio::io::{AsyncBufReadExt, AsyncReadExt, AsyncSeekExt}; -use tokio_test::assert_ok; #[tokio::test] async fn empty_read_is_cooperative() { @@ -38,9 +37,25 @@ async fn empty_seek() { let mut empty = tokio::io::empty(); - let pos = assert_ok!(empty.seek(SeekFrom::Start(0)).await); - assert_eq!(pos, 0); - - let pos = assert_ok!(empty.seek(SeekFrom::Start(8)).await); - assert_eq!(pos, 0); + 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) + )); } From 3bb5835db66601ed40ae940c7f436ffb17ab0fca Mon Sep 17 00:00:00 2001 From: Michael Macias Date: Sun, 30 Jun 2024 14:06:06 -0500 Subject: [PATCH 3/3] io: add inline attribute to `AsyncSeek` implementations This follows the style of the other trait implementations of `Empty`. See . --- tokio/src/io/util/empty.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tokio/src/io/util/empty.rs b/tokio/src/io/util/empty.rs index 372440f80e2..cc86e8b09a1 100644 --- a/tokio/src/io/util/empty.rs +++ b/tokio/src/io/util/empty.rs @@ -134,10 +134,12 @@ 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));