mirror of
https://github.com/tokio-rs/tokio.git
synced 2025-10-01 12:20:39 +00:00
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.
This commit is contained in:
parent
7ee5542182
commit
f28c9f0d17
@ -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(_) => {}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user