diff options
author | Jeb Rosen <jeb@jebrosen.com> | 2020-01-08 19:15:57 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-01-08 19:15:57 -0800 |
commit | f28c9f0d17a4dca2003bbee57a09f62c3795c2d2 (patch) | |
tree | c5314dc3d74ee7f8b5eb62221c3383fc49759c82 /tokio | |
parent | 7ee554218208a9f3919d840079bd96c6ba881caf (diff) |
Fix Seek adapter and AsyncSeek error handling for File
* io: Fix the Seek adapter and add a tested example.
If the first 'AsyncRead::start_seek' call returns Ready,
'AsyncRead::poll_complete' will be called.
Previously, a start_seek that immediately returned 'Ready' would cause
the Seek adapter to return 'Pending' without registering a Waker.
* fs: Do not return write errors from methods on AsyncSeek.
Write errors should only be returned on subsequent writes or on flush.
Also copy the last_write_err assert from 'poll_read' to both
'start_seek' and 'poll_complete' for consistency.
Diffstat (limited to 'tokio')
-rw-r--r-- | tokio/src/fs/file.rs | 10 | ||||
-rw-r--r-- | tokio/src/io/seek.rs | 16 | ||||
-rw-r--r-- | tokio/src/io/util/async_seek_ext.rs | 22 |
3 files changed, 32 insertions, 16 deletions
diff --git a/tokio/src/fs/file.rs b/tokio/src/fs/file.rs index 301d2380..9110831a 100644 --- a/tokio/src/fs/file.rs +++ b/tokio/src/fs/file.rs @@ -558,10 +558,6 @@ impl AsyncSeek for File { cx: &mut Context<'_>, mut pos: SeekFrom, ) -> Poll<io::Result<()>> { - if let Some(e) = self.last_write_err.take() { - return Ready(Err(e.into())); - } - loop { match self.state { Idle(ref mut buf_cell) => { @@ -592,6 +588,7 @@ impl AsyncSeek for File { match op { Operation::Read(_) => {} Operation::Write(Err(e)) => { + assert!(self.last_write_err.is_none()); self.last_write_err = Some(e.kind()); } Operation::Write(_) => {} @@ -603,10 +600,6 @@ impl AsyncSeek for File { } fn poll_complete(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<u64>> { - if let Some(e) = self.last_write_err.take() { - return Ready(Err(e.into())); - } - loop { match self.state { Idle(_) => panic!("must call start_seek before calling poll_complete"), @@ -617,6 +610,7 @@ impl AsyncSeek for File { match op { Operation::Read(_) => {} Operation::Write(Err(e)) => { + assert!(self.last_write_err.is_none()); self.last_write_err = Some(e.kind()); } Operation::Write(_) => {} diff --git a/tokio/src/io/seek.rs b/tokio/src/io/seek.rs index 080141f0..e3b5bf6b 100644 --- a/tokio/src/io/seek.rs +++ b/tokio/src/io/seek.rs @@ -31,14 +31,14 @@ where fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { let me = &mut *self; match me.pos { - Some(pos) => { - match Pin::new(&mut me.seek).start_seek(cx, pos) { - Poll::Ready(Ok(())) => me.pos = None, - Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), - Poll::Pending => (), - }; - Poll::Pending - } + Some(pos) => match Pin::new(&mut me.seek).start_seek(cx, pos) { + Poll::Ready(Ok(())) => { + me.pos = None; + Pin::new(&mut me.seek).poll_complete(cx) + } + Poll::Ready(Err(e)) => Poll::Ready(Err(e)), + Poll::Pending => Poll::Pending, + }, None => Pin::new(&mut me.seek).poll_complete(cx), } } diff --git a/tokio/src/io/util/async_seek_ext.rs b/tokio/src/io/util/async_seek_ext.rs index 3063884b..c7243c7f 100644 --- a/tokio/src/io/util/async_seek_ext.rs +++ b/tokio/src/io/util/async_seek_ext.rs @@ -3,6 +3,28 @@ use crate::io::AsyncSeek; use std::io::SeekFrom; /// An extension trait which adds utility methods to `AsyncSeek` types. +/// +/// # Examples +/// +/// ``` +/// use std::io::{Cursor, SeekFrom}; +/// use tokio::prelude::*; +/// +/// #[tokio::main] +/// async fn main() -> io::Result<()> { +/// let mut cursor = Cursor::new(b"abcdefg"); +/// +/// // the `seek` method is defined by this trait +/// cursor.seek(SeekFrom::Start(3)).await?; +/// +/// let mut buf = [0; 1]; +/// let n = cursor.read(&mut buf).await?; +/// assert_eq!(n, 1); +/// assert_eq!(buf, [b'd']); +/// +/// Ok(()) +/// } +/// ``` pub trait AsyncSeekExt: AsyncSeek { /// Creates a future which will seek an IO object, and then yield the /// new position in the object and the object itself. |