From bb76fc9b56444b0b347c73c6bec4a0adf5861ace Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 13:37:39 -0700 Subject: [PATCH 01/13] fs: start updating API documentation --- tokio-fs/src/file/mod.rs | 121 ++++++++++++++++++--------------------- 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/tokio-fs/src/file/mod.rs b/tokio-fs/src/file/mod.rs index d3cae8b55ac..7cfa7275444 100644 --- a/tokio-fs/src/file/mod.rs +++ b/tokio-fs/src/file/mod.rs @@ -44,32 +44,35 @@ use std::task::Poll; /// Create a new file and asynchronously write bytes to it: /// /// ```no_run -/// use tokio::prelude::{AsyncWrite, Future}; +/// #![feature(async_await)] /// -/// let task = tokio::fs::File::create("foo.txt") -/// .and_then(|mut file| file.poll_write(b"hello, world!")) -/// .map(|res| { -/// println!("{:?}", res); -/// }).map_err(|err| eprintln!("IO error: {:?}", err)); +/// use tokio::fs::File; +/// use tokio::prelude::*; /// -/// tokio::run(task); +/// # async fn dox() -> std::io::Result<()> { +/// let mut file = File::create("foo.txt").await?; +/// file.write_all(b"hello, world!").await?; +/// # Ok(()) +/// # } /// ``` /// /// Read the contents of a file into a buffer /// /// ```no_run -/// use tokio::prelude::{AsyncRead, Future}; +/// #![feature(async_await)] /// -/// let task = tokio::fs::File::open("foo.txt") -/// .and_then(|mut file| { -/// let mut contents = vec![]; -/// file.read_buf(&mut contents) -/// .map(|res| { -/// println!("{:?}", res); -/// }) -/// }).map_err(|err| eprintln!("IO error: {:?}", err)); +/// use tokio::fs::File; +/// use tokio::prelude::*; /// -/// tokio::run(task); +/// # async fn dox() -> std::io::Result<()> { +/// let mut file = File::open("foo.txt").await?; +/// +/// let mut contents = vec![]; +/// file.read_to_end(&mut contents).await?; +/// +/// println!("len = {}", contents.len()); +/// # Ok(()) +/// # } /// ``` #[derive(Debug)] pub struct File { @@ -93,17 +96,20 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::open("foo.txt").and_then(|file| { - /// // do something with the file ... - /// file.metadata().map(|md| println!("{:?}", md)) - /// }).map_err(|e| { - /// // handle errors - /// eprintln!("IO error: {:?}", e); - /// }); + /// use tokio::fs::File; + /// use tokio::prelude::*; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt").await?; + /// + /// let mut contents = vec![]; + /// file.read_to_end(&mut contents).await?; + /// + /// println!("len = {}", contents.len()); + /// # Ok(()) + /// # } /// ``` pub fn open

(path: P) -> OpenFuture

where @@ -131,18 +137,16 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|file| { - /// // do something with the created file ... - /// file.metadata().map(|md| println!("{:?}", md)) - /// }).map_err(|e| { - /// // handle errors - /// eprintln!("IO error: {:?}", e); - /// }); + /// use tokio::fs::File; + /// use tokio::prelude::*; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let mut file = File::create("foo.txt").await?; + /// file.write_all(b"hello, world!").await?; + /// # Ok(()) + /// # } /// ``` pub fn create

(path: P) -> CreateFuture

where @@ -156,11 +160,12 @@ impl File { /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html /// [file]: struct.File.html /// - /// Examples - /// ```no_run - /// use std::fs::File; + /// # Examples /// - /// let std_file = File::open("foo.txt").unwrap(); + /// ```no_run + /// // This line could block. It is not recommended to do this on the Tokio + /// // runtime. + /// let std_file = std::fs::File::open("foo.txt").unwrap(); /// let file = tokio::fs::File::from_std(std_file); /// ``` pub fn from_std(std: StdFile) -> File { @@ -179,22 +184,6 @@ impl File { /// # Errors /// /// Seeking to a negative offset is considered an error. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::prelude::Future; - /// use std::io::SeekFrom; - /// - /// let task = tokio::fs::File::open("foo.txt") - /// // move cursor 6 bytes from the start of the file - /// .and_then(|mut file| file.poll_seek(SeekFrom::Start(6))) - /// .map(|res| { - /// println!("{:?}", res); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); - /// - /// tokio::run(task); - /// ``` pub fn poll_seek(&mut self, pos: io::SeekFrom) -> Poll> { crate::blocking_io(|| self.std().seek(pos)) } @@ -209,17 +198,21 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] + /// + /// use tokio::fs::File; + /// use tokio::prelude::*; + /// /// use std::io::SeekFrom; /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|file| file.seek(SeekFrom::Start(6))) - /// .map(|file| { - /// // handle returned file .. - /// # println!("{:?}", file); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// # async fn dox() -> std::io::Result<()> { + /// let mut file = File::open("foo.txt").await?; + /// file.seek(SeekFrom::Start(6)).await?; /// - /// tokio::run(task); + /// let mut contents = vec![0u8; 10]; + /// file.read_exact(&mut contents).await?; + /// # Ok(()) + /// # } /// ``` pub fn seek(self, pos: io::SeekFrom) -> SeekFuture { SeekFuture::new(self, pos) From 8777ca3a6c4b7d07d65c767fee72188b1a551ac8 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 15:10:50 -0700 Subject: [PATCH 02/13] fs: polish File --- tokio-fs/Cargo.toml | 15 +- tokio-fs/src/file/mod.rs | 306 +++++++++--------------------- tokio-fs/src/file/open_options.rs | 19 +- tokio-fs/src/lib.rs | 19 +- tokio-fs/src/read.rs | 87 ++------- tokio-fs/src/write.rs | 99 ++-------- tokio/src/fs.rs | 9 +- 7 files changed, 160 insertions(+), 394 deletions(-) diff --git a/tokio-fs/Cargo.toml b/tokio-fs/Cargo.toml index c35894988a2..64dbb7b4194 100644 --- a/tokio-fs/Cargo.toml +++ b/tokio-fs/Cargo.toml @@ -24,15 +24,16 @@ categories = ["asynchronous", "network-programming", "filesystem"] publish = false [dependencies] -futures-core-preview = "0.3.0-alpha.17" -tokio-threadpool = { version = "0.2.0", path = "../tokio-threadpool" } tokio-io = { version = "0.2.0", path = "../tokio-io" } +tokio-threadpool = { version = "0.2.0", path = "../tokio-threadpool" } + +futures-core-preview = "= 0.3.0-alpha.17" +futures-util-preview = "= 0.3.0-alpha.17" [dev-dependencies] rand = "0.7" tempfile = "3" -tokio-codec = { version = "0.2.0", path = "../tokio-codec" } -tokio = { version = "0.2.0", path = "../tokio" } -futures-channel-preview = "0.3.0-alpha.17" -futures-preview = { version = "0.3.0-alpha.17" } -futures-util-preview = "0.3.0-alpha.17" +# tokio-codec = { version = "0.2.0", path = "../tokio-codec" } +tokio = { version = "*", path = "../tokio" } +# futures-preview = { version = "0.3.0-alpha.17" } +# futures-util-preview = "0.3.0-alpha.17" diff --git a/tokio-fs/src/file/mod.rs b/tokio-fs/src/file/mod.rs index 7cfa7275444..257230875aa 100644 --- a/tokio-fs/src/file/mod.rs +++ b/tokio-fs/src/file/mod.rs @@ -2,24 +2,16 @@ //! //! [`File`]: file/struct.File.html -mod clone; -mod create; -mod metadata; -mod open; mod open_options; -mod seek; -pub use self::clone::CloneFuture; -pub use self::create::CreateFuture; -pub use self::metadata::MetadataFuture; -pub use self::open::OpenFuture; pub use self::open_options::OpenOptions; -pub use self::seek::SeekFuture; + +use crate::asyncify; use tokio_io::{AsyncRead, AsyncWrite}; use std::convert::TryFrom; -use std::fs::{File as StdFile, Metadata, Permissions}; +use std::fs::{Metadata, Permissions}; use std::io::{self, Read, Seek, Write}; use std::path::Path; use std::pin::Pin; @@ -76,7 +68,7 @@ use std::task::Poll; /// ``` #[derive(Debug)] pub struct File { - std: Option, + std: std::fs::File, } impl File { @@ -88,10 +80,9 @@ impl File { /// /// # Errors /// - /// `OpenFuture` results in an error if called from outside of the Tokio - /// runtime or if the underlying [`open`] call results in an error. - /// - /// [`open`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.open + /// This function will return an error if called from outside of the Tokio + /// runtime or if path does not already exist. Other errors may also be + /// returned according to OpenOptions::open. /// /// # Examples /// @@ -111,11 +102,14 @@ impl File { /// # Ok(()) /// # } /// ``` - pub fn open

(path: P) -> OpenFuture

+ pub async fn open

(path: P) -> io::Result where P: AsRef + Send + Unpin + 'static, { - OpenOptions::new().read(true).open(path) + let mut open_options = OpenOptions::new(); + open_options.read(true); + + open_options.open(path).await } /// Opens a file in write-only mode. @@ -148,11 +142,12 @@ impl File { /// # Ok(()) /// # } /// ``` - pub fn create

(path: P) -> CreateFuture

+ pub async fn create

(path: P) -> io::Result where P: AsRef + Send + Unpin + 'static, { - CreateFuture::new(path) + let std_file = asyncify(|| std::fs::File::create(&path)).await?; + Ok(File::from_std(std_file)) } /// Convert a [`std::fs::File`][std] to a [`tokio_fs::File`][file]. @@ -168,24 +163,8 @@ impl File { /// let std_file = std::fs::File::open("foo.txt").unwrap(); /// let file = tokio::fs::File::from_std(std_file); /// ``` - pub fn from_std(std: StdFile) -> File { - File { std: Some(std) } - } - - /// Seek to an offset, in bytes, in a stream. - /// - /// A seek beyond the end of a stream is allowed, but implementation - /// defined. - /// - /// If the seek operation completed successfully, this method returns the - /// new position from the start of the stream. That position can be used - /// later with `SeekFrom::Start`. - /// - /// # Errors - /// - /// Seeking to a negative offset is considered an error. - pub fn poll_seek(&mut self, pos: io::SeekFrom) -> Poll> { - crate::blocking_io(|| self.std().seek(pos)) + pub fn from_std(std: std::fs::File) -> File { + File { std } } /// Seek to an offset, in bytes, in a stream. @@ -214,8 +193,8 @@ impl File { /// # Ok(()) /// # } /// ``` - pub fn seek(self, pos: io::SeekFrom) -> SeekFuture { - SeekFuture::new(self, pos) + pub async fn seek(&mut self, pos: io::SeekFrom) -> io::Result { + asyncify(|| self.std.seek(pos)).await } /// Attempts to sync all OS-internal metadata to disk. @@ -226,22 +205,20 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::{AsyncWrite, Future}; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|mut file| { - /// file.poll_write(b"hello, world!")?; - /// file.poll_sync_all() - /// }) - /// .map(|res| { - /// // handle returned result .. - /// # println!("{:?}", res); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// use tokio::fs::File; + /// use tokio::prelude::*; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let mut file = File::create("foo.txt").await?; + /// file.write_all(b"hello, world!").await?; + /// file.sync_all().await?; + /// # Ok(()) + /// # } /// ``` - pub fn poll_sync_all(&mut self) -> Poll> { - crate::blocking_io(|| self.std().sync_all()) + pub async fn sync_all(&mut self) -> io::Result<()> { + asyncify(|| self.std.sync_all()).await } /// This function is similar to `poll_sync_all`, except that it may not @@ -256,22 +233,20 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::{AsyncWrite, Future}; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|mut file| { - /// file.poll_write(b"hello, world!")?; - /// file.poll_sync_data() - /// }) - /// .map(|res| { - /// // handle returned result .. - /// # println!("{:?}", res); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// use tokio::fs::File; + /// use tokio::prelude::*; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let mut file = File::create("foo.txt").await?; + /// file.write_all(b"hello, world!").await?; + /// file.sync_data().await?; + /// # Ok(()) + /// # } /// ``` - pub fn poll_sync_data(&mut self) -> Poll> { - crate::blocking_io(|| self.std().sync_data()) + pub async fn sync_data(&mut self) -> io::Result<()> { + asyncify(|| self.std.sync_data()).await } /// Truncates or extends the underlying file, updating the size of this file to become size. @@ -289,40 +264,20 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; - /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|mut file| { - /// file.poll_set_len(10) - /// }) - /// .map(|res| { - /// // handle returned result .. - /// # println!("{:?}", res); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); - /// - /// tokio::run(task); - /// ``` - pub fn poll_set_len(&mut self, size: u64) -> Poll> { - crate::blocking_io(|| self.std().set_len(size)) - } - - /// Queries metadata about the underlying file. - /// - /// # Examples - /// - /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|file| file.metadata()) - /// .map(|metadata| { - /// println!("{:?}", metadata); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// use tokio::fs::File; + /// use tokio::prelude::*; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let mut file = File::create("foo.txt").await?; + /// file.write_all(b"hello, world!").await?; + /// file.set_len(10).await?; + /// # Ok(()) + /// # } /// ``` - pub fn metadata(self) -> MetadataFuture { - MetadataFuture::new(self) + pub async fn set_len(&mut self, size: u64) -> io::Result<()> { + asyncify(|| self.std.set_len(size)).await } /// Queries metadata about the underlying file. @@ -330,44 +285,20 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; - /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|mut file| file.poll_metadata()) - /// .map(|metadata| { - /// // metadata is of type Async::Ready - /// println!("{:?}", metadata); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); - /// - /// tokio::run(task); - /// ``` - pub fn poll_metadata(&mut self) -> Poll> { - crate::blocking_io(|| self.std().metadata()) - } - - /// Create a new `File` instance that shares the same underlying file handle - /// as the existing `File` instance. Reads, writes, and seeks will affect both - /// File instances simultaneously. - /// - /// # Examples + /// #![feature(async_await)] /// - /// ```no_run - /// use tokio::prelude::Future; + /// use tokio::fs::File; /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|mut file| file.poll_try_clone()) - /// .map(|clone| { - /// // do something with the clone - /// # println!("{:?}", clone); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// # async fn dox() -> std::io::Result<()> { + /// let file = File::open("foo.txt").await?; + /// let metadata = file.metadata().await?; /// - /// tokio::run(task); + /// println!("{:?}", metadata); + /// # Ok(()) + /// # } /// ``` - pub fn poll_try_clone(&mut self) -> Poll> { - crate::blocking_io(|| { - let std = self.std().try_clone()?; - Ok(File::from_std(std)) - }) + pub async fn metadata(&self) -> io::Result { + asyncify(|| self.std.metadata()).await } /// Create a new `File` instance that shares the same underlying file handle @@ -377,27 +308,19 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|file| { - /// file.try_clone() - /// .map(|(file, clone)| { - /// // do something with the file and the clone - /// # println!("{:?} {:?}", file, clone); - /// }) - /// .map_err(|(file, err)| { - /// // you get the original file back if there's an error - /// # println!("{:?}", file); - /// err - /// }) - /// }) - /// .map_err(|err| eprintln!("IO error: {:?}", err)); + /// use tokio::fs::File; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let file = File::open("foo.txt").await?; + /// let file_clone = file.try_clone().await?; + /// # Ok(()) + /// # } /// ``` - pub fn try_clone(self) -> CloneFuture { - CloneFuture::new(self) + pub async fn try_clone(&self) -> io::Result { + let std_file = asyncify(|| self.std.try_clone()).await?; + Ok(File::from_std(std_file)) } /// Changes the permissions on the underlying file. @@ -419,23 +342,20 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .and_then(|file| file.metadata()) - /// .map(|(mut file, metadata)| { - /// let mut perms = metadata.permissions(); - /// perms.set_readonly(true); - /// match file.poll_set_permissions(perms) { - /// Err(e) => eprintln!("{}", e), - /// _ => println!("permissions set!"), - /// } - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// use tokio::fs::File; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let file = File::open("foo.txt").await?; + /// let mut perms = file.metadata().await?.permissions(); + /// perms.set_readonly(true); + /// file.set_permissions(perms).await?; + /// # Ok(()) + /// # } /// ``` - pub fn poll_set_permissions(&mut self, perm: Permissions) -> Poll> { - crate::blocking_io(|| self.std().set_permissions(perm)) + pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> { + asyncify(|| self.std.set_permissions(perm)).await } /// Destructures the `tokio_fs::File` into a [`std::fs::File`][std]. @@ -460,18 +380,8 @@ impl File { /// /// tokio::run(task); /// ``` - pub fn into_std(mut self) -> StdFile { - self.std.take().expect("`File` instance already shutdown") - } - - fn std(&mut self) -> &mut StdFile { - self.std.as_mut().expect("`File` instance already shutdown") - } -} - -impl Read for File { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - crate::would_block(|| self.std().read(buf)) + pub fn into_std(self) -> std::fs::File { + self.std } } @@ -481,20 +391,7 @@ impl AsyncRead for File { _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - match Pin::get_mut(self).read(buf) { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } - } -} - -impl Write for File { - fn write(&mut self, buf: &[u8]) -> io::Result { - crate::would_block(|| self.std().write(buf)) - } - - fn flush(&mut self) -> io::Result<()> { - crate::would_block(|| self.std().flush()) + crate::blocking_io(|| (&self.std).read(buf)) } } @@ -504,17 +401,11 @@ impl AsyncWrite for File { _cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - match Pin::get_mut(self).write(buf) { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + crate::blocking_io(|| (&self.std).write(buf)) } fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - match Pin::get_mut(self).flush() { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + crate::blocking_io(|| (&self.std).flush()) } fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { @@ -522,27 +413,16 @@ impl AsyncWrite for File { } } -impl Drop for File { - fn drop(&mut self) { - if let Some(_std) = self.std.take() { - // This is probably fine as closing a file *shouldn't* be a blocking - // operation. That said, ideally `shutdown` is called first. - } - } -} - -impl From for File { - fn from(std: StdFile) -> Self { +impl From for File { + fn from(std: std::fs::File) -> Self { Self::from_std(std) } } -impl TryFrom for StdFile { +impl TryFrom for std::fs::File { type Error = io::Error; - fn try_from(mut file: File) -> Result { - file.std - .take() - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "`File` instance already shutdown")) + fn try_from(file: File) -> Result { + Ok(file.std) } } diff --git a/tokio-fs/src/file/open_options.rs b/tokio-fs/src/file/open_options.rs index 1a4f63c51c8..85b6f1db561 100644 --- a/tokio-fs/src/file/open_options.rs +++ b/tokio-fs/src/file/open_options.rs @@ -1,7 +1,7 @@ -use super::OpenFuture; +use super::File; -use std::convert::From; -use std::fs::OpenOptions as StdOpenOptions; +use futures_util::future::poll_fn; +use std::io; use std::path::Path; /// Options and flags which can be used to configure how a file is opened. @@ -14,7 +14,7 @@ use std::path::Path; /// /// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html #[derive(Clone, Debug)] -pub struct OpenOptions(StdOpenOptions); +pub struct OpenOptions(std::fs::OpenOptions); impl OpenOptions { /// Creates a blank new set of options ready for configuration. @@ -30,7 +30,7 @@ impl OpenOptions { /// let future = options.read(true).open("foo.txt"); /// ``` pub fn new() -> OpenOptions { - OpenOptions(StdOpenOptions::new()) + OpenOptions(std::fs::OpenOptions::new()) } /// See the underlying [`read`] call for details. @@ -89,16 +89,17 @@ impl OpenOptions { /// Tokio runtime or if the underlying [`open`] call results in an error. /// /// [`open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open - pub fn open

(&self, path: P) -> OpenFuture

+ pub async fn open

(&self, path: P) -> io::Result where P: AsRef + Send + Unpin + 'static, { - OpenFuture::new(self.0.clone(), path) + let std_file = poll_fn(|_| crate::blocking_io(|| self.0.open(&path))).await?; + Ok(File::from_std(std_file)) } } -impl From for OpenOptions { - fn from(options: StdOpenOptions) -> OpenOptions { +impl From for OpenOptions { + fn from(options: std::fs::OpenOptions) -> OpenOptions { OpenOptions(options) } } diff --git a/tokio-fs/src/lib.rs b/tokio-fs/src/lib.rs index f4376853985..e3eb1b686bd 100644 --- a/tokio-fs/src/lib.rs +++ b/tokio-fs/src/lib.rs @@ -2,6 +2,7 @@ #![deny(missing_docs, missing_debug_implementations, rust_2018_idioms)] #![cfg_attr(test, deny(warnings))] #![doc(test(no_crate_inject, attr(deny(rust_2018_idioms))))] +#![feature(async_await)] //! Asynchronous file and standard stream adaptation. //! @@ -56,7 +57,7 @@ pub use crate::file::File; pub use crate::file::OpenOptions; pub use crate::hard_link::{hard_link, HardLinkFuture}; pub use crate::metadata::{metadata, MetadataFuture}; -pub use crate::read::{read, ReadFile}; +pub use crate::read::read; pub use crate::read_dir::{read_dir, DirEntry, ReadDir, ReadDirFuture}; pub use crate::read_link::{read_link, ReadLinkFuture}; pub use crate::remove_dir::{remove_dir, RemoveDirFuture}; @@ -68,7 +69,7 @@ pub use crate::stderr::{stderr, Stderr}; pub use crate::stdin::{stdin, Stdin}; pub use crate::stdout::{stdout, Stdout}; pub use crate::symlink_metadata::{symlink_metadata, SymlinkMetadataFuture}; -pub use crate::write::{write, WriteFile}; +pub use crate::write::write; use std::io; use std::io::ErrorKind::{Other, WouldBlock}; @@ -86,6 +87,20 @@ where } } +async fn asyncify(f: F) -> io::Result +where + F: FnOnce() -> io::Result, +{ + use futures_util::future::poll_fn; + + let mut f = Some(f); + poll_fn(move |_| { + blocking_io(|| { + f.take().unwrap()() + }) + }).await +} + fn would_block(f: F) -> io::Result where F: FnOnce() -> io::Result, diff --git a/tokio-fs/src/read.rs b/tokio-fs/src/read.rs index 1baed103ba3..4b2cf05a79a 100644 --- a/tokio-fs/src/read.rs +++ b/tokio-fs/src/read.rs @@ -1,13 +1,8 @@ -use crate::{file, File}; +use crate::File; -use tokio_io::AsyncRead; +use tokio_io::AsyncReadExt; -use futures_core::ready; -use std::future::Future; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; -use std::{io, mem, path::Path}; +use std::{io, path::Path}; /// Creates a future which will open a file for reading and read the entire /// contents into a buffer and return said buffer. @@ -17,74 +12,24 @@ use std::{io, mem, path::Path}; /// # Examples /// /// ```no_run -/// use tokio::prelude::Future; +/// #![feature(async_await)] /// -/// let task = tokio::fs::read("foo.txt").map(|data| { -/// // do something with the contents of the file ... -/// println!("foo.txt contains {} bytes", data.len()); -/// }).map_err(|e| { -/// // handle errors -/// eprintln!("IO error: {:?}", e); -/// }); +/// use tokio::fs; /// -/// tokio::run(task); +/// # async fn dox() -> std::io::Result<()> { +/// let contents = fs::read("foo.txt").await?; +/// println!("foo.txt contains {} bytes", contents.len()); +/// # Ok(()) +/// # } /// ``` -pub fn read

(path: P) -> ReadFile

+pub async fn read

(path: P) -> io::Result> where P: AsRef + Send + Unpin + 'static, { - ReadFile { - state: State::Open(File::open(path)), - } -} - -/// A future used to open a file and read its entire contents into a buffer. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadFile + Send + Unpin + 'static> { - state: State

, -} - -#[derive(Debug)] -enum State + Send + Unpin + 'static> { - Open(file::OpenFuture

), - Metadata(file::MetadataFuture), - Reading(Vec, usize, File), - Empty, -} - -impl + Send + Unpin + 'static> Future for ReadFile

{ - type Output = io::Result>; + let mut file = File::open(path).await?; + let metadata = file.metadata().await?; - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let inner = Pin::get_mut(self); - match &mut inner.state { - State::Open(ref mut open_file) => { - let file = ready!(Pin::new(open_file).poll(cx))?; - let new_state = State::Metadata(file.metadata()); - mem::replace(&mut inner.state, new_state); - Pin::new(inner).poll(cx) - } - State::Metadata(read_metadata) => { - let (file, metadata) = ready!(Pin::new(read_metadata).poll(cx))?; - let buf = Vec::with_capacity(metadata.len() as usize + 1); - let new_state = State::Reading(buf, 0, file); - mem::replace(&mut inner.state, new_state); - Pin::new(inner).poll(cx) - } - State::Reading(buf, ref mut pos, file) => { - let n = ready!(Pin::new(file).poll_read_buf(cx, buf))?; - *pos += n; - if *pos >= buf.len() { - match mem::replace(&mut inner.state, State::Empty) { - State::Reading(buf, _, _) => Poll::Ready(Ok(buf)), - _ => panic!(), - } - } else { - Poll::Pending - } - } - State::Empty => panic!("poll a WriteFile after it's done"), - } - } + let mut contents = Vec::with_capacity(metadata.len() as usize + 1); + file.read_to_end(&mut contents).await?; + Ok(contents) } diff --git a/tokio-fs/src/write.rs b/tokio-fs/src/write.rs index 701d2d3b990..1db4a0a368e 100644 --- a/tokio-fs/src/write.rs +++ b/tokio-fs/src/write.rs @@ -1,13 +1,8 @@ -use crate::{file, File}; +use crate::File; -use tokio_io::AsyncWrite; +use tokio_io::AsyncWriteExt; -use futures_core::ready; -use std::future::Future; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; -use std::{fmt, io, mem, path::Path}; +use std::{io, path::Path}; /// Creates a future that will open a file for writing and write the entire /// contents of `contents` to it. @@ -17,89 +12,21 @@ use std::{fmt, io, mem, path::Path}; /// # Examples /// /// ```no_run -/// use tokio::prelude::Future; +/// #![feature(async_await)] /// -/// let buffer = b"Hello world!"; -/// let task = tokio::fs::write("foo.txt", buffer).map(|data| { -/// // `data` has now been written to foo.txt. The buffer is being -/// // returned so it can be used for other things. -/// println!("foo.txt now had {} bytes written to it", data.len()); -/// }).map_err(|e| { -/// // handle errors -/// eprintln!("IO error: {:?}", e); -/// }); +/// use tokio::fs; /// -/// tokio::run(task); +/// # async fn dox() -> std::io::Result<()> { +/// fs::write("foo.txt", b"Hello world!").await?; +/// # Ok(()) +/// # } /// ``` -pub fn write + Unpin>(path: P, contents: C) -> WriteFile +pub async fn write + Unpin>(path: P, contents: C) -> io::Result<()> where P: AsRef + Send + Unpin + 'static, { - WriteFile { - state: State::Create(File::create(path), Some(contents)), - } -} - -/// A future used to open a file for writing and write the entire contents -/// of some data to it. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct WriteFile + Send + Unpin + 'static, C: AsRef<[u8]> + Unpin> { - state: State, -} - -#[derive(Debug)] -enum State + Send + Unpin + 'static, C: AsRef<[u8]> + Unpin> { - Create(file::CreateFuture

, Option), - Writing { f: File, buf: C, pos: usize }, - Empty, -} - -fn zero_write() -> io::Error { - io::Error::new(io::ErrorKind::WriteZero, "zero-length write") -} - -impl + Send + Unpin + 'static, C: AsRef<[u8]> + Unpin + fmt::Debug> Future - for WriteFile -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let inner = Pin::get_mut(self); - match &mut inner.state { - State::Create(create_file, contents) => { - let file = ready!(Pin::new(create_file).poll(cx))?; - let contents = contents.take().unwrap(); - let new_state = State::Writing { - f: file, - buf: contents, - pos: 0, - }; - mem::replace(&mut inner.state, new_state); - // We just entered the Write state, need to poll it before returning. - return Pin::new(inner).poll(cx); - } - State::Empty => panic!("poll a WriteFile after it's done"), - _ => {} - } + let mut file = File::create(path).await?; + file.write_all(contents.as_ref()).await?; - match mem::replace(&mut inner.state, State::Empty) { - State::Writing { - mut f, - buf, - mut pos, - } => { - let buf_ref = buf.as_ref(); - while pos < buf_ref.len() { - let n = ready!(Pin::new(&mut f).poll_write(cx, &buf_ref[pos..]))?; - pos += n; - if n == 0 { - return Poll::Ready(Err(zero_write())); - } - } - Poll::Ready(Ok(buf)) - } - _ => panic!(), - } - } + Ok(()) } diff --git a/tokio/src/fs.rs b/tokio/src/fs.rs index 4831b93e2c5..a42379a8be6 100644 --- a/tokio/src/fs.rs +++ b/tokio/src/fs.rs @@ -7,11 +7,8 @@ //! the context of the Tokio runtime as they require Tokio specific features to //! function. -pub use tokio_fs::OpenOptions; pub use tokio_fs::{ - create_dir, create_dir_all, file, hard_link, metadata, os, read_dir, read_link, -}; -pub use tokio_fs::{read, write, ReadFile, WriteFile}; -pub use tokio_fs::{ - remove_dir, remove_dir_all, remove_file, rename, set_permissions, symlink_metadata, File, + create_dir, create_dir_all, file, hard_link, metadata, os, read, read_dir, read_link, + remove_dir, remove_dir_all, remove_file, rename, set_permissions, symlink_metadata, write, + File, OpenOptions, }; From e767c83fa5bf9766825c14d3fbfd7fa9eeb5e87a Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 15:12:04 -0700 Subject: [PATCH 03/13] remove unused files --- tokio-fs/src/file/clone.rs | 41 ----------------------------------- tokio-fs/src/file/create.rs | 40 ---------------------------------- tokio-fs/src/file/metadata.rs | 41 ----------------------------------- tokio-fs/src/file/open.rs | 41 ----------------------------------- tokio-fs/src/file/seek.rs | 40 ---------------------------------- 5 files changed, 203 deletions(-) delete mode 100644 tokio-fs/src/file/clone.rs delete mode 100644 tokio-fs/src/file/create.rs delete mode 100644 tokio-fs/src/file/metadata.rs delete mode 100644 tokio-fs/src/file/open.rs delete mode 100644 tokio-fs/src/file/seek.rs diff --git a/tokio-fs/src/file/clone.rs b/tokio-fs/src/file/clone.rs deleted file mode 100644 index bec790338dc..00000000000 --- a/tokio-fs/src/file/clone.rs +++ /dev/null @@ -1,41 +0,0 @@ -use super::File; - -use std::future::Future; -use std::io; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; - -/// Future returned by `File::try_clone`. -/// -/// Clones a file handle into two file handles. -/// -/// # Panics -/// -/// Will panic if polled after returning an item or error. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct CloneFuture { - file: Option, -} - -impl CloneFuture { - pub(crate) fn new(file: File) -> Self { - Self { file: Some(file) } - } -} - -impl Future for CloneFuture { - type Output = Result<(File, File), (File, io::Error)>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let inner_self = Pin::get_mut(self); - inner_self - .file - .as_mut() - .expect("Cannot poll `CloneFuture` after it resolves") - .poll_try_clone() - .map(|inner| inner.map(|cloned| (inner_self.file.take().unwrap(), cloned))) - .map_err(|err| (inner_self.file.take().unwrap(), err)) - } -} diff --git a/tokio-fs/src/file/create.rs b/tokio-fs/src/file/create.rs deleted file mode 100644 index 65feef6c00e..00000000000 --- a/tokio-fs/src/file/create.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::File; - -use futures_core::ready; -use std::fs::File as StdFile; -use std::future::Future; -use std::io; -use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; - -/// Future returned by `File::create` and resolves to a `File` instance. -#[must_use = "futures do nothing unless you `.await` or poll them"] -#[derive(Debug)] -pub struct CreateFuture

{ - path: P, -} - -impl

CreateFuture

-where - P: AsRef + Send + Unpin + 'static, -{ - pub(crate) fn new(path: P) -> Self { - CreateFuture { path } - } -} - -impl

Future for CreateFuture

-where - P: AsRef + Send + Unpin + 'static, -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let std = ready!(crate::blocking_io(|| StdFile::create(&self.path)))?; - - let file = File::from_std(std); - Poll::Ready(Ok(file)) - } -} diff --git a/tokio-fs/src/file/metadata.rs b/tokio-fs/src/file/metadata.rs deleted file mode 100644 index a29f17d8c26..00000000000 --- a/tokio-fs/src/file/metadata.rs +++ /dev/null @@ -1,41 +0,0 @@ -use super::File; - -use futures_core::ready; -use std::fs::File as StdFile; -use std::fs::Metadata; -use std::future::Future; -use std::io; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; - -const POLL_AFTER_RESOLVE: &str = "Cannot poll MetadataFuture after it resolves"; - -/// Future returned by `File::metadata` and resolves to a `(File, Metadata)` instance. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct MetadataFuture { - file: Option, -} - -impl MetadataFuture { - pub(crate) fn new(file: File) -> Self { - MetadataFuture { file: Some(file) } - } - - fn std(&mut self) -> &mut StdFile { - self.file.as_mut().expect(POLL_AFTER_RESOLVE).std() - } -} - -impl Future for MetadataFuture { - type Output = io::Result<(File, Metadata)>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let inner = Pin::get_mut(self); - let metadata = ready!(crate::blocking_io(|| StdFile::metadata(inner.std())))?; - - let file = inner.file.take().expect(POLL_AFTER_RESOLVE); - Poll::Ready(Ok((file, metadata))) - } -} diff --git a/tokio-fs/src/file/open.rs b/tokio-fs/src/file/open.rs deleted file mode 100644 index d8fa36ccb79..00000000000 --- a/tokio-fs/src/file/open.rs +++ /dev/null @@ -1,41 +0,0 @@ -use super::File; - -use futures_core::ready; -use std::fs::OpenOptions as StdOpenOptions; -use std::future::Future; -use std::io; -use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; - -/// Future returned by `File::open` and resolves to a `File` instance. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct OpenFuture { - options: StdOpenOptions, - path: P, -} - -impl

OpenFuture

-where - P: AsRef + Send + Unpin + 'static, -{ - pub(crate) fn new(options: StdOpenOptions, path: P) -> Self { - OpenFuture { options, path } - } -} - -impl

Future for OpenFuture

-where - P: AsRef + Send + Unpin + 'static, -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let std = ready!(crate::blocking_io(|| self.options.open(&self.path)))?; - - let file = File::from_std(std); - Poll::Ready(Ok(file)) - } -} diff --git a/tokio-fs/src/file/seek.rs b/tokio-fs/src/file/seek.rs deleted file mode 100644 index cf99cc373f0..00000000000 --- a/tokio-fs/src/file/seek.rs +++ /dev/null @@ -1,40 +0,0 @@ -use super::File; - -use futures_core::ready; -use std::future::Future; -use std::io; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; - -/// Future returned by `File::seek`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct SeekFuture { - inner: Option, - pos: io::SeekFrom, -} - -impl SeekFuture { - pub(crate) fn new(file: File, pos: io::SeekFrom) -> Self { - Self { - pos, - inner: Some(file), - } - } -} - -impl Future for SeekFuture { - type Output = io::Result<(File, u64)>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - let inner_self = Pin::get_mut(self); - let pos = ready!(inner_self - .inner - .as_mut() - .expect("Cannot poll `SeekFuture` after it resolves") - .poll_seek(inner_self.pos))?; - let inner = inner_self.inner.take().unwrap(); - Poll::Ready(Ok((inner, pos))) - } -} From 5c1c64575ada08f882ca577fd465adb2a6da4b73 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 15:26:11 -0700 Subject: [PATCH 04/13] fs: update read_dir --- tokio-fs/src/create_dir.rs | 41 ++------------------- tokio-fs/src/create_dir_all.rs | 41 ++------------------- tokio-fs/src/hard_link.rs | 45 ++--------------------- tokio-fs/src/lib.rs | 24 ++++++------ tokio-fs/src/metadata.rs | 42 ++------------------- tokio-fs/src/read_dir.rs | 67 +++++++++++----------------------- 6 files changed, 49 insertions(+), 211 deletions(-) diff --git a/tokio-fs/src/create_dir.rs b/tokio-fs/src/create_dir.rs index 9f245dc4122..19133c2d98f 100644 --- a/tokio-fs/src/create_dir.rs +++ b/tokio-fs/src/create_dir.rs @@ -1,46 +1,13 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Creates a new, empty directory at the provided path /// /// This is an async version of [`std::fs::create_dir`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.create_dir.html -pub fn create_dir>(path: P) -> CreateDirFuture

{ - CreateDirFuture::new(path) -} - -/// Future returned by `create_dir`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct CreateDirFuture

-where - P: AsRef, -{ - path: P, -} - -impl

CreateDirFuture

-where - P: AsRef, -{ - fn new(path: P) -> CreateDirFuture

{ - CreateDirFuture { path } - } -} - -impl

Future for CreateDirFuture

-where - P: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::create_dir(&self.path)) - } +pub async fn create_dir>(path: P) -> io::Result<()> { + asyncify(|| std::fs::create_dir(&path)).await } diff --git a/tokio-fs/src/create_dir_all.rs b/tokio-fs/src/create_dir_all.rs index 37e675bee2e..3bbcbabddb1 100644 --- a/tokio-fs/src/create_dir_all.rs +++ b/tokio-fs/src/create_dir_all.rs @@ -1,10 +1,7 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Recursively create a directory and all of its parent components if they /// are missing. @@ -12,36 +9,6 @@ use std::task::Poll; /// This is an async version of [`std::fs::create_dir_all`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.create_dir_all.html -pub fn create_dir_all>(path: P) -> CreateDirAllFuture

{ - CreateDirAllFuture::new(path) -} - -/// Future returned by `create_dir_all`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct CreateDirAllFuture

-where - P: AsRef, -{ - path: P, -} - -impl

CreateDirAllFuture

-where - P: AsRef, -{ - fn new(path: P) -> CreateDirAllFuture

{ - CreateDirAllFuture { path } - } -} - -impl

Future for CreateDirAllFuture

-where - P: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::create_dir_all(&self.path)) - } +pub async fn create_dir_all>(path: P) -> io::Result<()> { + asyncify(|| std::fs::create_dir_all(&path)).await } diff --git a/tokio-fs/src/hard_link.rs b/tokio-fs/src/hard_link.rs index 39ee90b5936..3d1fe82a406 100644 --- a/tokio-fs/src/hard_link.rs +++ b/tokio-fs/src/hard_link.rs @@ -1,10 +1,7 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Creates a new hard link on the filesystem. /// @@ -14,40 +11,6 @@ use std::task::Poll; /// This is an async version of [`std::fs::hard_link`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.hard_link.html -pub fn hard_link, Q: AsRef>(src: P, dst: Q) -> HardLinkFuture { - HardLinkFuture::new(src, dst) -} - -/// Future returned by `hard_link`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct HardLinkFuture -where - P: AsRef, - Q: AsRef, -{ - src: P, - dst: Q, -} - -impl HardLinkFuture -where - P: AsRef, - Q: AsRef, -{ - fn new(src: P, dst: Q) -> HardLinkFuture { - HardLinkFuture { src, dst } - } -} - -impl Future for HardLinkFuture -where - P: AsRef, - Q: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::hard_link(&self.src, &self.dst)) - } +pub async fn hard_link, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { + asyncify(|| std::fs::hard_link(&src, &dst)).await } diff --git a/tokio-fs/src/lib.rs b/tokio-fs/src/lib.rs index e3eb1b686bd..b97d4950d2d 100644 --- a/tokio-fs/src/lib.rs +++ b/tokio-fs/src/lib.rs @@ -51,24 +51,24 @@ mod stdout; mod symlink_metadata; mod write; -pub use crate::create_dir::{create_dir, CreateDirFuture}; -pub use crate::create_dir_all::{create_dir_all, CreateDirAllFuture}; +pub use crate::create_dir::create_dir; +pub use crate::create_dir_all::create_dir_all; pub use crate::file::File; pub use crate::file::OpenOptions; -pub use crate::hard_link::{hard_link, HardLinkFuture}; -pub use crate::metadata::{metadata, MetadataFuture}; +pub use crate::hard_link::hard_link; +pub use crate::metadata::metadata; pub use crate::read::read; -pub use crate::read_dir::{read_dir, DirEntry, ReadDir, ReadDirFuture}; -pub use crate::read_link::{read_link, ReadLinkFuture}; -pub use crate::remove_dir::{remove_dir, RemoveDirFuture}; -pub use crate::remove_dir_all::{remove_dir_all, RemoveDirAllFuture}; -pub use crate::remove_file::{remove_file, RemoveFileFuture}; -pub use crate::rename::{rename, RenameFuture}; -pub use crate::set_permissions::{set_permissions, SetPermissionsFuture}; +pub use crate::read_dir::{read_dir, DirEntry, ReadDir}; +pub use crate::read_link::read_link; +pub use crate::remove_dir::remove_dir; +pub use crate::remove_dir_all::remove_dir_all; +pub use crate::remove_file::remove_file; +pub use crate::rename::rename; +pub use crate::set_permissions::set_permissions; pub use crate::stderr::{stderr, Stderr}; pub use crate::stdin::{stdin, Stdin}; pub use crate::stdout::{stdout, Stdout}; -pub use crate::symlink_metadata::{symlink_metadata, SymlinkMetadataFuture}; +pub use crate::symlink_metadata::symlink_metadata; pub use crate::write::write; use std::io; diff --git a/tokio-fs/src/metadata.rs b/tokio-fs/src/metadata.rs index 7d05f299c07..145c92e0c50 100644 --- a/tokio-fs/src/metadata.rs +++ b/tokio-fs/src/metadata.rs @@ -1,47 +1,13 @@ -use super::blocking_io; +use crate::asyncify; -use std::fs::{self, Metadata}; -use std::future::Future; +use std::fs::Metadata; use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Queries the file system metadata for a path. -pub fn metadata

(path: P) -> MetadataFuture

+pub async fn metadata

(path: P) -> io::Result where P: AsRef + Send + 'static, { - MetadataFuture::new(path) -} - -/// Future returned by `metadata`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct MetadataFuture

-where - P: AsRef + Send + 'static, -{ - path: P, -} - -impl

MetadataFuture

-where - P: AsRef + Send + 'static, -{ - pub(crate) fn new(path: P) -> Self { - Self { path } - } -} - -impl

Future for MetadataFuture

-where - P: AsRef + Send + 'static, -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - blocking_io(|| fs::metadata(&self.path)) - } + asyncify(|| std::fs::metadata(&path)).await } diff --git a/tokio-fs/src/read_dir.rs b/tokio-fs/src/read_dir.rs index cf93903e50d..a166c94ee3e 100644 --- a/tokio-fs/src/read_dir.rs +++ b/tokio-fs/src/read_dir.rs @@ -1,7 +1,8 @@ +use crate::{asyncify, blocking_io}; + use futures_core::stream::Stream; use std::ffi::OsString; -use std::fs::{self, DirEntry as StdDirEntry, FileType, Metadata, ReadDir as StdReadDir}; -use std::future::Future; +use std::fs::{DirEntry as StdDirEntry, FileType, Metadata}; use std::io; #[cfg(unix)] use std::os::unix::fs::DirEntryExt; @@ -15,41 +16,12 @@ use std::task::Poll; /// This is an async version of [`std::fs::read_dir`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.read_dir.html -pub fn read_dir

(path: P) -> ReadDirFuture

+pub async fn read_dir

(path: P) -> io::Result where P: AsRef + Send + 'static, { - ReadDirFuture::new(path) -} - -/// Future returned by `read_dir`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadDirFuture

-where - P: AsRef + Send + 'static, -{ - path: P, -} - -impl

ReadDirFuture

-where - P: AsRef + Send + 'static, -{ - fn new(path: P) -> ReadDirFuture

{ - ReadDirFuture { path } - } -} - -impl

Future for ReadDirFuture

-where - P: AsRef + Send + 'static, -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| Ok(ReadDir(fs::read_dir(&self.path)?))) - } + let std = asyncify(|| std::fs::read_dir(&path)).await?; + Ok(ReadDir(std)) } /// Stream of the entries in a directory. @@ -70,18 +42,21 @@ where /// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err #[derive(Debug)] #[must_use = "streams do nothing unless polled"] -pub struct ReadDir(StdReadDir); +pub struct ReadDir(std::fs::ReadDir); impl Stream for ReadDir { type Item = io::Result; - fn poll_next(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - let inner = Pin::get_mut(self); - match crate::blocking_io(|| match inner.0.next() { - Some(Err(err)) => Err(err), - Some(Ok(item)) => Ok(Some(Ok(DirEntry(item)))), - None => Ok(None), - }) { + fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + let res = blocking_io(|| { + match self.0.next() { + Some(Err(err)) => Err(err), + Some(Ok(item)) => Ok(Some(Ok(DirEntry(item)))), + None => Ok(None), + } + }); + + match res { Poll::Ready(Err(err)) => Poll::Ready(Some(Err(err))), Poll::Ready(Ok(v)) => Poll::Ready(v), Poll::Pending => Poll::Pending, @@ -190,8 +165,8 @@ impl DirEntry { /// /// tokio::run(fut); /// ``` - pub fn poll_metadata(&self) -> Poll> { - crate::blocking_io(|| self.0.metadata()) + pub async fn metadata(&self) -> io::Result { + asyncify(|| self.0.metadata()).await } /// Return the file type for the file that this entry points at. @@ -222,8 +197,8 @@ impl DirEntry { /// /// tokio::run(fut); /// ``` - pub fn poll_file_type(&self) -> Poll> { - crate::blocking_io(|| self.0.file_type()) + pub async fn file_type(&self) -> io::Result { + asyncify(|| self.0.file_type()).await } } From 1740b476dbf941d90a67c24a2bbbc7fe029c29e4 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 20:37:19 -0700 Subject: [PATCH 05/13] more updates --- tokio-fs/src/file/mod.rs | 8 ++--- tokio-fs/src/lib.rs | 17 +--------- tokio-fs/src/os/unix.rs | 44 +++--------------------- tokio-fs/src/os/windows/mod.rs | 4 +-- tokio-fs/src/os/windows/symlink_dir.rs | 44 +++--------------------- tokio-fs/src/os/windows/symlink_file.rs | 44 +++--------------------- tokio-fs/src/read_link.rs | 41 +++------------------- tokio-fs/src/remove_dir.rs | 41 +++------------------- tokio-fs/src/remove_dir_all.rs | 41 +++------------------- tokio-fs/src/remove_file.rs | 41 +++------------------- tokio-fs/src/rename.rs | 45 +++---------------------- tokio-fs/src/set_permissions.rs | 43 +++-------------------- tokio-fs/src/stderr.rs | 30 +++++------------ tokio-fs/src/stdin.rs | 19 ++++------- tokio-fs/src/stdout.rs | 30 +++++------------ tokio-fs/src/symlink_metadata.rs | 42 +++-------------------- 16 files changed, 70 insertions(+), 464 deletions(-) diff --git a/tokio-fs/src/file/mod.rs b/tokio-fs/src/file/mod.rs index 257230875aa..683545f8462 100644 --- a/tokio-fs/src/file/mod.rs +++ b/tokio-fs/src/file/mod.rs @@ -6,7 +6,7 @@ mod open_options; pub use self::open_options::OpenOptions; -use crate::asyncify; +use crate::{asyncify, blocking_io}; use tokio_io::{AsyncRead, AsyncWrite}; @@ -391,7 +391,7 @@ impl AsyncRead for File { _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - crate::blocking_io(|| (&self.std).read(buf)) + blocking_io(|| (&self.std).read(buf)) } } @@ -401,11 +401,11 @@ impl AsyncWrite for File { _cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - crate::blocking_io(|| (&self.std).write(buf)) + blocking_io(|| (&self.std).write(buf)) } fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - crate::blocking_io(|| (&self.std).flush()) + blocking_io(|| (&self.std).flush()) } fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { diff --git a/tokio-fs/src/lib.rs b/tokio-fs/src/lib.rs index b97d4950d2d..5ba37e4afe9 100644 --- a/tokio-fs/src/lib.rs +++ b/tokio-fs/src/lib.rs @@ -72,7 +72,7 @@ pub use crate::symlink_metadata::symlink_metadata; pub use crate::write::write; use std::io; -use std::io::ErrorKind::{Other, WouldBlock}; +use std::io::ErrorKind::Other; use std::task::Poll; use std::task::Poll::*; @@ -101,21 +101,6 @@ where }).await } -fn would_block(f: F) -> io::Result -where - F: FnOnce() -> io::Result, -{ - match tokio_threadpool::blocking(f) { - Ready(Ok(Ok(v))) => Ok(v), - Ready(Ok(Err(err))) => { - debug_assert_ne!(err.kind(), WouldBlock); - Err(err) - } - Ready(Err(_)) => Err(blocking_err()), - Pending => Err(blocking_err()), - } -} - fn blocking_err() -> io::Error { io::Error::new( Other, diff --git a/tokio-fs/src/os/unix.rs b/tokio-fs/src/os/unix.rs index e8e222f278e..36f517564aa 100644 --- a/tokio-fs/src/os/unix.rs +++ b/tokio-fs/src/os/unix.rs @@ -1,12 +1,9 @@ //! Unix-specific extensions to primitives in the `tokio_fs` module. -use std::future::Future; +use crate::asyncify; + use std::io; -use std::os::unix::fs; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Creates a new symbolic link on the filesystem. /// @@ -15,39 +12,6 @@ use std::task::Poll; /// This is an async version of [`std::os::unix::fs::symlink`][std] /// /// [std]: https://doc.rust-lang.org/std/os/unix/fs/fn.symlink.html -pub fn symlink, Q: AsRef>(src: P, dst: Q) -> SymlinkFuture { - SymlinkFuture::new(src, dst) -} - -/// Future returned by `symlink`. -#[derive(Debug)] -pub struct SymlinkFuture -where - P: AsRef, - Q: AsRef, -{ - src: P, - dst: Q, -} - -impl SymlinkFuture -where - P: AsRef, - Q: AsRef, -{ - fn new(src: P, dst: Q) -> SymlinkFuture { - SymlinkFuture { src, dst } - } -} - -impl Future for SymlinkFuture -where - P: AsRef, - Q: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::symlink(&self.src, &self.dst)) - } +pub async fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { + asyncify(|| std::os::unix::fs::symlink(&src, &dst)).await } diff --git a/tokio-fs/src/os/windows/mod.rs b/tokio-fs/src/os/windows/mod.rs index eaeed043eb3..12ed8458a4b 100644 --- a/tokio-fs/src/os/windows/mod.rs +++ b/tokio-fs/src/os/windows/mod.rs @@ -3,5 +3,5 @@ mod symlink_dir; mod symlink_file; -pub use self::symlink_dir::{symlink_dir, SymlinkDirFuture}; -pub use self::symlink_file::{symlink_file, SymlinkFileFuture}; +pub use self::symlink_dir::symlink_dir; +pub use self::symlink_file::symlink_file; diff --git a/tokio-fs/src/os/windows/symlink_dir.rs b/tokio-fs/src/os/windows/symlink_dir.rs index a9181396f62..d5f72ad3da1 100644 --- a/tokio-fs/src/os/windows/symlink_dir.rs +++ b/tokio-fs/src/os/windows/symlink_dir.rs @@ -1,10 +1,7 @@ -use std::future::Future; +use crate::asyncify; + use std::io; -use std::os::windows::fs; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Creates a new directory symlink on the filesystem. /// @@ -14,39 +11,6 @@ use std::task::Poll; /// This is an async version of [`std::os::windows::fs::symlink_dir`][std] /// /// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_dir.html -pub fn symlink_dir, Q: AsRef>(src: P, dst: Q) -> SymlinkDirFuture { - SymlinkDirFuture::new(src, dst) -} - -/// Future returned by `symlink_dir`. -#[derive(Debug)] -pub struct SymlinkDirFuture -where - P: AsRef, - Q: AsRef, -{ - src: P, - dst: Q, -} - -impl SymlinkDirFuture -where - P: AsRef, - Q: AsRef, -{ - fn new(src: P, dst: Q) -> SymlinkDirFuture { - SymlinkDirFuture { src, dst } - } -} - -impl Future for SymlinkDirFuture -where - P: AsRef, - Q: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::symlink_dir(&self.src, &self.dst)) - } +pub async fn symlink_dir, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { + asyncify(|| std::os::windows::fs::symlink_dir(&src, &dst)).await } diff --git a/tokio-fs/src/os/windows/symlink_file.rs b/tokio-fs/src/os/windows/symlink_file.rs index 42d1563a5f2..7373355df75 100644 --- a/tokio-fs/src/os/windows/symlink_file.rs +++ b/tokio-fs/src/os/windows/symlink_file.rs @@ -1,10 +1,7 @@ -use std::future::Future; +use crate::asyncify; + use std::io; -use std::os::windows::fs; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Creates a new file symbolic link on the filesystem. /// @@ -14,39 +11,6 @@ use std::task::Poll; /// This is an async version of [`std::os::windows::fs::symlink_file`][std] /// /// [std]: https://doc.rust-lang.org/std/os/windows/fs/fn.symlink_file.html -pub fn symlink_file, Q: AsRef>(src: P, dst: Q) -> SymlinkFileFuture { - SymlinkFileFuture::new(src, dst) -} - -/// Future returned by `symlink_file`. -#[derive(Debug)] -pub struct SymlinkFileFuture -where - P: AsRef, - Q: AsRef, -{ - src: P, - dst: Q, -} - -impl SymlinkFileFuture -where - P: AsRef, - Q: AsRef, -{ - fn new(src: P, dst: Q) -> SymlinkFileFuture { - SymlinkFileFuture { src, dst } - } -} - -impl Future for SymlinkFileFuture -where - P: AsRef, - Q: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::symlink_file(&self.src, &self.dst)) - } +pub async fn symlink_file, Q: AsRef>(src: P, dst: Q) -> io::Result<()> { + asyncify(|| std::os::windows::fs::symlink_file(&src, &dst)).await } diff --git a/tokio-fs/src/read_link.rs b/tokio-fs/src/read_link.rs index 3898267f4d8..ac070abe0b8 100644 --- a/tokio-fs/src/read_link.rs +++ b/tokio-fs/src/read_link.rs @@ -1,46 +1,13 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::{Path, PathBuf}; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Reads a symbolic link, returning the file that the link points to. /// /// This is an async version of [`std::fs::read_link`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.read_link.html -pub fn read_link>(path: P) -> ReadLinkFuture

{ - ReadLinkFuture::new(path) -} - -/// Future returned by `read_link`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct ReadLinkFuture

-where - P: AsRef, -{ - path: P, -} - -impl

ReadLinkFuture

-where - P: AsRef, -{ - fn new(path: P) -> ReadLinkFuture

{ - ReadLinkFuture { path } - } -} - -impl

Future for ReadLinkFuture

-where - P: AsRef, -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::read_link(&self.path)) - } +pub async fn read_link>(path: P) -> io::Result { + asyncify(|| std::fs::read_link(&path)).await } diff --git a/tokio-fs/src/remove_dir.rs b/tokio-fs/src/remove_dir.rs index 0281ba918ac..0de7e33b645 100644 --- a/tokio-fs/src/remove_dir.rs +++ b/tokio-fs/src/remove_dir.rs @@ -1,46 +1,13 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Removes an existing, empty directory. /// /// This is an async version of [`std::fs::remove_dir`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html -pub fn remove_dir>(path: P) -> RemoveDirFuture

{ - RemoveDirFuture::new(path) -} - -/// Future returned by `remove_dir`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct RemoveDirFuture

-where - P: AsRef, -{ - path: P, -} - -impl

RemoveDirFuture

-where - P: AsRef, -{ - fn new(path: P) -> RemoveDirFuture

{ - RemoveDirFuture { path } - } -} - -impl

Future for RemoveDirFuture

-where - P: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::remove_dir(&self.path)) - } +pub async fn remove_dir>(path: P) -> io::Result<()> { + asyncify(|| std::fs::remove_dir(&path)).await } diff --git a/tokio-fs/src/remove_dir_all.rs b/tokio-fs/src/remove_dir_all.rs index d2eab6491f2..bd50697e15c 100644 --- a/tokio-fs/src/remove_dir_all.rs +++ b/tokio-fs/src/remove_dir_all.rs @@ -1,46 +1,13 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Removes a directory at this path, after removing all its contents. Use carefully! /// /// This is an async version of [`std::fs::remove_dir_all`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.remove_dir_all.html -pub fn remove_dir_all>(path: P) -> RemoveDirAllFuture

{ - RemoveDirAllFuture::new(path) -} - -/// Future returned by `remove_dir_all`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct RemoveDirAllFuture

-where - P: AsRef, -{ - path: P, -} - -impl

RemoveDirAllFuture

-where - P: AsRef, -{ - fn new(path: P) -> RemoveDirAllFuture

{ - RemoveDirAllFuture { path } - } -} - -impl

Future for RemoveDirAllFuture

-where - P: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::remove_dir_all(&self.path)) - } +pub async fn remove_dir_all>(path: P) -> io::Result<()> { + asyncify(|| std::fs::remove_dir_all(&path)).await } diff --git a/tokio-fs/src/remove_file.rs b/tokio-fs/src/remove_file.rs index 9eaa792985e..b5c2216c50f 100644 --- a/tokio-fs/src/remove_file.rs +++ b/tokio-fs/src/remove_file.rs @@ -1,10 +1,7 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Removes a file from the filesystem. /// @@ -15,36 +12,6 @@ use std::task::Poll; /// This is an async version of [`std::fs::remove_file`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.remove_file.html -pub fn remove_file>(path: P) -> RemoveFileFuture

{ - RemoveFileFuture::new(path) -} - -/// Future returned by `remove_file`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct RemoveFileFuture

-where - P: AsRef, -{ - path: P, -} - -impl

RemoveFileFuture

-where - P: AsRef, -{ - fn new(path: P) -> RemoveFileFuture

{ - RemoveFileFuture { path } - } -} - -impl

Future for RemoveFileFuture

-where - P: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::remove_file(&self.path)) - } +pub async fn remove_file>(path: P) -> io::Result<()> { + asyncify(|| std::fs::remove_file(&path)).await } diff --git a/tokio-fs/src/rename.rs b/tokio-fs/src/rename.rs index e766a826de3..e0f138aab62 100644 --- a/tokio-fs/src/rename.rs +++ b/tokio-fs/src/rename.rs @@ -1,10 +1,7 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Rename a file or directory to a new name, replacing the original file if /// `to` already exists. @@ -14,40 +11,6 @@ use std::task::Poll; /// This is an async version of [`std::fs::rename`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.rename.html -pub fn rename, Q: AsRef>(from: P, to: Q) -> RenameFuture { - RenameFuture::new(from, to) -} - -/// Future returned by `rename`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct RenameFuture -where - P: AsRef, - Q: AsRef, -{ - from: P, - to: Q, -} - -impl RenameFuture -where - P: AsRef, - Q: AsRef, -{ - fn new(from: P, to: Q) -> RenameFuture { - RenameFuture { from, to } - } -} - -impl Future for RenameFuture -where - P: AsRef, - Q: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::rename(&self.from, &self.to)) - } +pub async fn rename, Q: AsRef>(from: P, to: Q) -> io::Result<()> { + asyncify(|| std::fs::rename(&from, &to)).await } diff --git a/tokio-fs/src/set_permissions.rs b/tokio-fs/src/set_permissions.rs index fb8e97a3546..cd11d2d70ce 100644 --- a/tokio-fs/src/set_permissions.rs +++ b/tokio-fs/src/set_permissions.rs @@ -1,47 +1,14 @@ -use std::fs; -use std::future::Future; +use crate::asyncify; + +use std::fs::Permissions; use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Changes the permissions found on a file or a directory. /// /// This is an async version of [`std::fs::set_permissions`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.set_permissions.html -pub fn set_permissions>(path: P, perm: fs::Permissions) -> SetPermissionsFuture

{ - SetPermissionsFuture::new(path, perm) -} - -/// Future returned by `set_permissions`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct SetPermissionsFuture

-where - P: AsRef, -{ - path: P, - perm: fs::Permissions, -} - -impl

SetPermissionsFuture

-where - P: AsRef, -{ - fn new(path: P, perm: fs::Permissions) -> SetPermissionsFuture

{ - SetPermissionsFuture { path, perm } - } -} - -impl

Future for SetPermissionsFuture

-where - P: AsRef, -{ - type Output = io::Result<()>; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - crate::blocking_io(|| fs::set_permissions(&self.path, self.perm.clone())) - } +pub async fn set_permissions>(path: P, perm: Permissions) -> io::Result<()> { + asyncify(|| std::fs::set_permissions(&path, perm)).await } diff --git a/tokio-fs/src/stderr.rs b/tokio-fs/src/stderr.rs index e8654b28e48..d16132b6e7e 100644 --- a/tokio-fs/src/stderr.rs +++ b/tokio-fs/src/stderr.rs @@ -1,6 +1,8 @@ +use crate::blocking_io; + use tokio_io::AsyncWrite; -use std::io::{self, Stderr as StdStderr, Write}; +use std::io::{self, Write}; use std::pin::Pin; use std::task::Context; use std::task::Poll; @@ -16,7 +18,7 @@ use std::task::Poll; /// [`AsyncWrite`]: trait.AsyncWrite.html #[derive(Debug)] pub struct Stderr { - std: StdStderr, + std: std::io::Stderr, } /// Constructs a new handle to the standard error of the current process. @@ -28,33 +30,17 @@ pub fn stderr() -> Stderr { Stderr { std } } -impl Write for Stderr { - fn write(&mut self, buf: &[u8]) -> io::Result { - crate::would_block(|| self.std.write(buf)) - } - - fn flush(&mut self) -> io::Result<()> { - crate::would_block(|| self.std.flush()) - } -} - impl AsyncWrite for Stderr { fn poll_write( - self: Pin<&mut Self>, + mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - match Pin::get_mut(self).write(buf) { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + blocking_io(|| (&mut self.std).write(buf)) } - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - match Pin::get_mut(self).flush() { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + blocking_io(|| (&mut self.std).flush()) } fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { diff --git a/tokio-fs/src/stdin.rs b/tokio-fs/src/stdin.rs index 41ce7a2aafe..aa09bd9aa67 100644 --- a/tokio-fs/src/stdin.rs +++ b/tokio-fs/src/stdin.rs @@ -1,6 +1,8 @@ +use crate::blocking_io; + use tokio_io::AsyncRead; -use std::io::{self, Read, Stdin as StdStdin}; +use std::io::{self, Read}; use std::pin::Pin; use std::task::Context; use std::task::Poll; @@ -22,7 +24,7 @@ use std::task::Poll; /// [`AsyncRead`]: trait.AsyncRead.html #[derive(Debug)] pub struct Stdin { - std: StdStdin, + std: std::io::Stdin, } /// Constructs a new handle to the standard input of the current process. @@ -34,21 +36,12 @@ pub fn stdin() -> Stdin { Stdin { std } } -impl Read for Stdin { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - crate::would_block(|| self.std.read(buf)) - } -} - impl AsyncRead for Stdin { fn poll_read( - self: Pin<&mut Self>, + mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &mut [u8], ) -> Poll> { - match Pin::get_mut(self).read(buf) { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + blocking_io(|| (&mut self.std).read(buf)) } } diff --git a/tokio-fs/src/stdout.rs b/tokio-fs/src/stdout.rs index be9e0c69389..0c96e960f8a 100644 --- a/tokio-fs/src/stdout.rs +++ b/tokio-fs/src/stdout.rs @@ -1,6 +1,8 @@ +use crate::blocking_io; + use tokio_io::AsyncWrite; -use std::io::{self, Stdout as StdStdout, Write}; +use std::io::{self, Write}; use std::pin::Pin; use std::task::Context; use std::task::Poll; @@ -16,7 +18,7 @@ use std::task::Poll; /// [`AsyncWrite`]: trait.AsyncWrite.html #[derive(Debug)] pub struct Stdout { - std: StdStdout, + std: std::io::Stdout, } /// Constructs a new handle to the standard output of the current process. @@ -28,33 +30,17 @@ pub fn stdout() -> Stdout { Stdout { std } } -impl Write for Stdout { - fn write(&mut self, buf: &[u8]) -> io::Result { - crate::would_block(|| self.std.write(buf)) - } - - fn flush(&mut self) -> io::Result<()> { - crate::would_block(|| self.std.flush()) - } -} - impl AsyncWrite for Stdout { fn poll_write( - self: Pin<&mut Self>, + mut self: Pin<&mut Self>, _cx: &mut Context<'_>, buf: &[u8], ) -> Poll> { - match Pin::get_mut(self).write(buf) { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + blocking_io(|| (&mut self.std).write(buf)) } - fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - match Pin::get_mut(self).flush() { - Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => Poll::Pending, - other => Poll::Ready(other), - } + fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { + blocking_io(|| (&mut self.std).flush()) } fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { diff --git a/tokio-fs/src/symlink_metadata.rs b/tokio-fs/src/symlink_metadata.rs index bd880417b31..73fd910f90b 100644 --- a/tokio-fs/src/symlink_metadata.rs +++ b/tokio-fs/src/symlink_metadata.rs @@ -1,51 +1,17 @@ -use super::blocking_io; +use super::asyncify; -use std::fs::{self, Metadata}; -use std::future::Future; +use std::fs::Metadata; use std::io; use std::path::Path; -use std::pin::Pin; -use std::task::Context; -use std::task::Poll; /// Queries the file system metadata for a path. /// /// This is an async version of [`std::fs::symlink_metadata`][std] /// /// [std]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html -pub fn symlink_metadata

(path: P) -> SymlinkMetadataFuture

+pub async fn symlink_metadata

(path: P) -> io::Result where P: AsRef + Send + 'static, { - SymlinkMetadataFuture::new(path) -} - -/// Future returned by `symlink_metadata`. -#[derive(Debug)] -#[must_use = "futures do nothing unless you `.await` or poll them"] -pub struct SymlinkMetadataFuture

-where - P: AsRef + Send + 'static, -{ - path: P, -} - -impl

SymlinkMetadataFuture

-where - P: AsRef + Send + 'static, -{ - pub(crate) fn new(path: P) -> Self { - Self { path } - } -} - -impl

Future for SymlinkMetadataFuture

-where - P: AsRef + Send + 'static, -{ - type Output = io::Result; - - fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { - blocking_io(|| fs::symlink_metadata(&self.path)) - } + asyncify(|| std::fs::symlink_metadata(&path)).await } From 13773c2e969fe351227be40c15f6b2a398383670 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 20:43:15 -0700 Subject: [PATCH 06/13] reorg a few more files --- tokio-fs/src/{file/mod.rs => file.rs} | 6 +----- tokio-fs/src/lib.rs | 5 +++-- tokio-fs/src/{file => }/open_options.rs | 0 tokio-fs/src/os/mod.rs | 1 + tokio-fs/src/os/unix/mod.rs | 5 +++++ tokio-fs/src/os/{unix.rs => unix/symlink.rs} | 2 -- 6 files changed, 10 insertions(+), 9 deletions(-) rename tokio-fs/src/{file/mod.rs => file.rs} (99%) rename tokio-fs/src/{file => }/open_options.rs (100%) create mode 100644 tokio-fs/src/os/unix/mod.rs rename tokio-fs/src/os/{unix.rs => unix/symlink.rs} (87%) diff --git a/tokio-fs/src/file/mod.rs b/tokio-fs/src/file.rs similarity index 99% rename from tokio-fs/src/file/mod.rs rename to tokio-fs/src/file.rs index 683545f8462..24c21cd49ca 100644 --- a/tokio-fs/src/file/mod.rs +++ b/tokio-fs/src/file.rs @@ -2,11 +2,7 @@ //! //! [`File`]: file/struct.File.html -mod open_options; - -pub use self::open_options::OpenOptions; - -use crate::{asyncify, blocking_io}; +use crate::{asyncify, blocking_io, OpenOptions}; use tokio_io::{AsyncRead, AsyncWrite}; diff --git a/tokio-fs/src/lib.rs b/tokio-fs/src/lib.rs index 5ba37e4afe9..5261e705d43 100644 --- a/tokio-fs/src/lib.rs +++ b/tokio-fs/src/lib.rs @@ -33,9 +33,10 @@ mod create_dir; mod create_dir_all; -pub mod file; +mod file; mod hard_link; mod metadata; +mod open_options; pub mod os; mod read; mod read_dir; @@ -54,9 +55,9 @@ mod write; pub use crate::create_dir::create_dir; pub use crate::create_dir_all::create_dir_all; pub use crate::file::File; -pub use crate::file::OpenOptions; pub use crate::hard_link::hard_link; pub use crate::metadata::metadata; +pub use crate::open_options::OpenOptions; pub use crate::read::read; pub use crate::read_dir::{read_dir, DirEntry, ReadDir}; pub use crate::read_link::read_link; diff --git a/tokio-fs/src/file/open_options.rs b/tokio-fs/src/open_options.rs similarity index 100% rename from tokio-fs/src/file/open_options.rs rename to tokio-fs/src/open_options.rs diff --git a/tokio-fs/src/os/mod.rs b/tokio-fs/src/os/mod.rs index ae57c484761..f4b8bfb617d 100644 --- a/tokio-fs/src/os/mod.rs +++ b/tokio-fs/src/os/mod.rs @@ -2,5 +2,6 @@ #[cfg(unix)] pub mod unix; + #[cfg(windows)] pub mod windows; diff --git a/tokio-fs/src/os/unix/mod.rs b/tokio-fs/src/os/unix/mod.rs new file mode 100644 index 00000000000..c3bb562fef4 --- /dev/null +++ b/tokio-fs/src/os/unix/mod.rs @@ -0,0 +1,5 @@ +//! Unix-specific extensions to primitives in the `tokio_fs` module. + +mod symlink; + +pub use self::symlink::symlink; diff --git a/tokio-fs/src/os/unix.rs b/tokio-fs/src/os/unix/symlink.rs similarity index 87% rename from tokio-fs/src/os/unix.rs rename to tokio-fs/src/os/unix/symlink.rs index 36f517564aa..bfc8a6cfd14 100644 --- a/tokio-fs/src/os/unix.rs +++ b/tokio-fs/src/os/unix/symlink.rs @@ -1,5 +1,3 @@ -//! Unix-specific extensions to primitives in the `tokio_fs` module. - use crate::asyncify; use std::io; From e6efd9b3ac89f034e9602bf8ab8cd39a651bc61a Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Fri, 2 Aug 2019 20:49:56 -0700 Subject: [PATCH 07/13] wip dox --- tokio-fs/src/file.rs | 15 +++++++-------- tokio-fs/src/read_dir.rs | 20 +++++++++++++------- tokio/src/fs.rs | 6 +++--- 3 files changed, 23 insertions(+), 18 deletions(-) diff --git a/tokio-fs/src/file.rs b/tokio-fs/src/file.rs index 24c21cd49ca..951e7a5268b 100644 --- a/tokio-fs/src/file.rs +++ b/tokio-fs/src/file.rs @@ -365,16 +365,15 @@ impl File { /// # Examples /// /// ```no_run - /// use tokio::prelude::Future; + /// #![feature(async_await)] /// - /// let task = tokio::fs::File::create("foo.txt") - /// .map(|file| { - /// let std_file = file.into_std(); - /// // do something with the std::fs::File - /// # println!("{:?}", std_file); - /// }).map_err(|err| eprintln!("IO error: {:?}", err)); + /// use tokio::fs::File; /// - /// tokio::run(task); + /// # async fn dox() -> std::io::Result<()> { + /// let file = File::create("foo.txt").await?; + /// let std_file = file.into_std(); + /// # Ok(()) + /// # } /// ``` pub fn into_std(self) -> std::fs::File { self.std diff --git a/tokio-fs/src/read_dir.rs b/tokio-fs/src/read_dir.rs index a166c94ee3e..9b014fe95d8 100644 --- a/tokio-fs/src/read_dir.rs +++ b/tokio-fs/src/read_dir.rs @@ -94,15 +94,21 @@ impl DirEntry { /// /// # Examples /// - /// ``` - /// use futures::{Future, Stream}; + /// ```no_run + /// #![feature(async_await)] /// - /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| { - /// println!("{:?}", dir.path()); - /// Ok(()) - /// }).map_err(|err| { eprintln!("Error: {:?}", err); () }); + /// use tokio::fs; + /// use tokio::prelude::*; /// - /// tokio::run(fut); + /// # async fn dox() -> std::io::Result<()> { + /// let mut entries = fs::read_dir(".").await?; + /// + /// while let Some(entry) = entries.next().await { + /// let dir = entry?; + /// println!("{:?}", dir.path()); + /// } + /// # Ok(()) + /// # } /// ``` /// /// This prints output like: diff --git a/tokio/src/fs.rs b/tokio/src/fs.rs index a42379a8be6..75f493aae0e 100644 --- a/tokio/src/fs.rs +++ b/tokio/src/fs.rs @@ -8,7 +8,7 @@ //! function. pub use tokio_fs::{ - create_dir, create_dir_all, file, hard_link, metadata, os, read, read_dir, read_link, - remove_dir, remove_dir_all, remove_file, rename, set_permissions, symlink_metadata, write, - File, OpenOptions, + create_dir, create_dir_all, hard_link, metadata, os, read, read_dir, read_link, remove_dir, + remove_dir_all, remove_file, rename, set_permissions, symlink_metadata, write, File, + OpenOptions, }; From 490a828b7b445194230161682e595b810733be40 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 3 Aug 2019 22:18:07 -0700 Subject: [PATCH 08/13] get more doc examples working --- tokio-fs/src/read_dir.rs | 86 +++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/tokio-fs/src/read_dir.rs b/tokio-fs/src/read_dir.rs index 9b014fe95d8..017c3f6dcd9 100644 --- a/tokio-fs/src/read_dir.rs +++ b/tokio-fs/src/read_dir.rs @@ -103,9 +103,9 @@ impl DirEntry { /// # async fn dox() -> std::io::Result<()> { /// let mut entries = fs::read_dir(".").await?; /// - /// while let Some(entry) = entries.next().await { - /// let dir = entry?; - /// println!("{:?}", dir.path()); + /// while let Some(res) = entries.next().await { + /// let entry = res?; + /// println!("{:?}", entry.path()); /// } /// # Ok(()) /// # } @@ -130,15 +130,20 @@ impl DirEntry { /// # Examples /// /// ``` - /// use futures::{Future, Stream}; + /// #![feature(async_await)] /// - /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| { - /// // Here, `dir` is a `DirEntry`. - /// println!("{:?}", dir.file_name()); - /// Ok(()) - /// }).map_err(|err| { eprintln!("Error: {:?}", err); () }); + /// use tokio::fs; + /// use tokio::prelude::*; /// - /// tokio::run(fut); + /// # async fn dox() -> std::io::Result<()> { + /// let mut entries = fs::read_dir(".").await?; + /// + /// while let Some(res) = entries.next().await { + /// let entry = res?; + /// println!("{:?}", entry.file_name()); + /// } + /// # Ok(()) + /// # } /// ``` pub fn file_name(&self) -> OsString { self.0.file_name() @@ -158,18 +163,26 @@ impl DirEntry { /// # Examples /// /// ``` - /// use futures::{Future, Stream}; - /// use futures::future::poll_fn; - /// - /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| { - /// // Here, `dir` is a `DirEntry`. - /// let path = dir.path(); - /// poll_fn(move || dir.poll_metadata()).map(move |metadata| { - /// println!("{:?}: {:?}", path, metadata.permissions()); - /// }) - /// }).map_err(|err| { eprintln!("Error: {:?}", err); () }); - /// - /// tokio::run(fut); + /// #![feature(async_await)] + /// + /// use tokio::fs; + /// use tokio::prelude::*; + /// + /// # async fn dox() -> std::io::Result<()> { + /// let mut entries = fs::read_dir(".").await?; + /// + /// while let Some(res) = entries.next().await { + /// let entry = res?; + /// + /// if let Ok(metadata) = entry.metadata().await { + /// // Now let's show our entry's permissions! + /// println!("{:?}: {:?}", entry.path(), metadata.permissions()); + /// } else { + /// println!("Couldn't get file type for {:?}", entry.path()); + /// } + /// } + /// # Ok(()) + /// # } /// ``` pub async fn metadata(&self) -> io::Result { asyncify(|| self.0.metadata()).await @@ -189,19 +202,26 @@ impl DirEntry { /// # Examples /// /// ``` - /// use futures::{Future, Stream}; - /// use futures::future::poll_fn; + /// #![feature(async_await)] /// - /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| { - /// // Here, `dir` is a `DirEntry`. - /// let path = dir.path(); - /// poll_fn(move || dir.poll_file_type()).map(move |file_type| { - /// // Now let's show our entry's file type! - /// println!("{:?}: {:?}", path, file_type); - /// }) - /// }).map_err(|err| { eprintln!("Error: {:?}", err); () }); + /// use tokio::fs; + /// use tokio::prelude::*; /// - /// tokio::run(fut); + /// # async fn dox() -> std::io::Result<()> { + /// let mut entries = fs::read_dir(".").await?; + /// + /// while let Some(res) = entries.next().await { + /// let entry = res?; + /// + /// if let Ok(file_type) = entry.file_type().await { + /// // Now let's show our entry's file type! + /// println!("{:?}: {:?}", entry.path(), file_type); + /// } else { + /// println!("Couldn't get file type for {:?}", entry.path()); + /// } + /// } + /// # Ok(()) + /// # } /// ``` pub async fn file_type(&self) -> io::Result { asyncify(|| self.0.file_type()).await From f2e7e477443b572e540c7c736b3173b688258b03 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sat, 3 Aug 2019 22:19:01 -0700 Subject: [PATCH 09/13] fmt --- tokio-fs/src/lib.rs | 6 +----- tokio-fs/src/read_dir.rs | 10 ++++------ 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/tokio-fs/src/lib.rs b/tokio-fs/src/lib.rs index 5261e705d43..be936adf405 100644 --- a/tokio-fs/src/lib.rs +++ b/tokio-fs/src/lib.rs @@ -95,11 +95,7 @@ where use futures_util::future::poll_fn; let mut f = Some(f); - poll_fn(move |_| { - blocking_io(|| { - f.take().unwrap()() - }) - }).await + poll_fn(move |_| blocking_io(|| f.take().unwrap()())).await } fn blocking_err() -> io::Error { diff --git a/tokio-fs/src/read_dir.rs b/tokio-fs/src/read_dir.rs index 017c3f6dcd9..f3f12ace07b 100644 --- a/tokio-fs/src/read_dir.rs +++ b/tokio-fs/src/read_dir.rs @@ -48,12 +48,10 @@ impl Stream for ReadDir { type Item = io::Result; fn poll_next(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { - let res = blocking_io(|| { - match self.0.next() { - Some(Err(err)) => Err(err), - Some(Ok(item)) => Ok(Some(Ok(DirEntry(item)))), - None => Ok(None), - } + let res = blocking_io(|| match self.0.next() { + Some(Err(err)) => Err(err), + Some(Ok(item)) => Ok(Some(Ok(DirEntry(item)))), + None => Ok(None), }); match res { From 0d2f6b84210b520bd1ea2cb99a8c5cd2c96ef16c Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sun, 4 Aug 2019 00:07:10 -0700 Subject: [PATCH 10/13] fix tests --- tokio-fs/tests/file.rs | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/tokio-fs/tests/file.rs b/tokio-fs/tests/file.rs index e2e02865452..93cf33e1510 100644 --- a/tokio-fs/tests/file.rs +++ b/tokio-fs/tests/file.rs @@ -1,7 +1,6 @@ #![deny(warnings, rust_2018_idioms)] #![feature(async_await)] -use futures_util::future::poll_fn; use rand::{distributions, thread_rng, Rng}; use std::fs; use std::io::SeekFrom; @@ -31,11 +30,11 @@ fn read_write() { let contents_2 = contents.clone(); pool::run(async move { - let file = File::create(file_path).await?; - let (mut file, metadata) = file.metadata().await?; + let mut file = File::create(file_path).await?; + let metadata = file.metadata().await?; assert!(metadata.is_file()); file.write(&contents).await?; - poll_fn(move |_cx| file.poll_sync_all()).await?; + file.sync_all().await?; Ok(()) }); @@ -109,19 +108,21 @@ fn seek() { let file_path = dir.path().join("seek.txt"); pool::run(async move { - let mut file = OpenOptions::new() + let mut options = OpenOptions::new(); + + options .create(true) .read(true) - .write(true) - .open(file_path) - .await - .unwrap(); + .write(true); + + let mut file = options.open(file_path).await.unwrap(); + assert!(file.write(b"Hello, world!").await.is_ok()); - let mut file = file.seek(SeekFrom::End(-6)).await.unwrap().0; + file.seek(SeekFrom::End(-6)).await.unwrap(); let mut buf = vec![0; 5]; assert!(file.read(buf.as_mut()).await.is_ok()); assert_eq!(buf, b"world"); - let mut file = file.seek(SeekFrom::Start(0)).await.unwrap().0; + file.seek(SeekFrom::Start(0)).await.unwrap(); let mut buf = vec![0; 5]; assert!(file.read(buf.as_mut()).await.is_ok()); assert_eq!(buf, b"Hello"); @@ -141,8 +142,8 @@ fn clone() { let file_path_2 = file_path.clone(); pool::run(async move { - let file = File::create(file_path.clone()).await.unwrap(); - let (mut file, mut clone) = file.try_clone().await.unwrap(); + let mut file = File::create(file_path.clone()).await.unwrap(); + let mut clone = file.try_clone().await.unwrap(); assert!(AsyncWriteExt::write(&mut file, b"clone ").await.is_ok()); assert!(AsyncWriteExt::write(&mut clone, b"successful") .await From 584fd38ee27369799e14241a5d13e8514b3d2321 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sun, 4 Aug 2019 00:10:39 -0700 Subject: [PATCH 11/13] fmt --- tokio-fs/tests/file.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tokio-fs/tests/file.rs b/tokio-fs/tests/file.rs index 93cf33e1510..480053d4f38 100644 --- a/tokio-fs/tests/file.rs +++ b/tokio-fs/tests/file.rs @@ -110,10 +110,7 @@ fn seek() { pool::run(async move { let mut options = OpenOptions::new(); - options - .create(true) - .read(true) - .write(true); + options.create(true).read(true).write(true); let mut file = options.open(file_path).await.unwrap(); From 812b25ad629838f5bd09c5a8be36fe691fda3c93 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sun, 4 Aug 2019 09:54:48 -0700 Subject: [PATCH 12/13] fix clippy --- tokio-fs/src/file.rs | 7 +++++++ tokio-fs/src/open_options.rs | 1 + tokio-fs/src/read_dir.rs | 2 ++ 3 files changed, 10 insertions(+) diff --git a/tokio-fs/src/file.rs b/tokio-fs/src/file.rs index 951e7a5268b..ca7c6b574f3 100644 --- a/tokio-fs/src/file.rs +++ b/tokio-fs/src/file.rs @@ -189,6 +189,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn seek(&mut self, pos: io::SeekFrom) -> io::Result { asyncify(|| self.std.seek(pos)).await } @@ -213,6 +214,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn sync_all(&mut self) -> io::Result<()> { asyncify(|| self.std.sync_all()).await } @@ -241,6 +243,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn sync_data(&mut self) -> io::Result<()> { asyncify(|| self.std.sync_data()).await } @@ -272,6 +275,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn set_len(&mut self, size: u64) -> io::Result<()> { asyncify(|| self.std.set_len(size)).await } @@ -293,6 +297,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn metadata(&self) -> io::Result { asyncify(|| self.std.metadata()).await } @@ -314,6 +319,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn try_clone(&self) -> io::Result { let std_file = asyncify(|| self.std.try_clone()).await?; Ok(File::from_std(std_file)) @@ -350,6 +356,7 @@ impl File { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> { asyncify(|| self.std.set_permissions(perm)).await } diff --git a/tokio-fs/src/open_options.rs b/tokio-fs/src/open_options.rs index 85b6f1db561..ff979772d05 100644 --- a/tokio-fs/src/open_options.rs +++ b/tokio-fs/src/open_options.rs @@ -89,6 +89,7 @@ impl OpenOptions { /// Tokio runtime or if the underlying [`open`] call results in an error. /// /// [`open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.open + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn open

(&self, path: P) -> io::Result where P: AsRef + Send + Unpin + 'static, diff --git a/tokio-fs/src/read_dir.rs b/tokio-fs/src/read_dir.rs index f3f12ace07b..33209e7524b 100644 --- a/tokio-fs/src/read_dir.rs +++ b/tokio-fs/src/read_dir.rs @@ -182,6 +182,7 @@ impl DirEntry { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn metadata(&self) -> io::Result { asyncify(|| self.0.metadata()).await } @@ -221,6 +222,7 @@ impl DirEntry { /// # Ok(()) /// # } /// ``` + #[allow(clippy::needless_lifetimes)] // false positive: https://github.com/rust-lang/rust-clippy/issues/3988 pub async fn file_type(&self) -> io::Result { asyncify(|| self.0.file_type()).await } From 3f6edc9e4181681dbe071d626f0d87eaa0a42429 Mon Sep 17 00:00:00 2001 From: Carl Lerche Date: Sun, 4 Aug 2019 11:10:25 -0700 Subject: [PATCH 13/13] doc tweaks --- tokio-fs/src/file.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/tokio-fs/src/file.rs b/tokio-fs/src/file.rs index ca7c6b574f3..ca1e14a0f3f 100644 --- a/tokio-fs/src/file.rs +++ b/tokio-fs/src/file.rs @@ -119,8 +119,8 @@ impl File { /// /// # Errors /// - /// `CreateFuture` results in an error if called from outside of the Tokio - /// runtime or if the underlying [`create`] call results in an error. + /// Results in an error if called from outside of the Tokio runtime or if + /// the underlying [`create`] call results in an error. /// /// [`create`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.create /// @@ -165,11 +165,6 @@ impl File { /// Seek to an offset, in bytes, in a stream. /// - /// Similar to `poll_seek`, but returning a `Future`. - /// - /// This method consumes the `File` and returns it back when the future - /// completes. - /// /// # Examples /// /// ```no_run