summaryrefslogtreecommitdiffstats
path: root/third_party/rust/tokio-fs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/tokio-fs')
-rw-r--r--third_party/rust/tokio-fs/.cargo-checksum.json1
-rw-r--r--third_party/rust/tokio-fs/CHANGELOG.md18
-rw-r--r--third_party/rust/tokio-fs/Cargo.toml46
-rw-r--r--third_party/rust/tokio-fs/LICENSE25
-rw-r--r--third_party/rust/tokio-fs/README.md19
-rw-r--r--third_party/rust/tokio-fs/examples/std-echo.rs48
-rw-r--r--third_party/rust/tokio-fs/src/create_dir.rs46
-rw-r--r--third_party/rust/tokio-fs/src/create_dir_all.rs47
-rw-r--r--third_party/rust/tokio-fs/src/file/create.rs37
-rw-r--r--third_party/rust/tokio-fs/src/file/metadata.rs39
-rw-r--r--third_party/rust/tokio-fs/src/file/mod.rs243
-rw-r--r--third_party/rust/tokio-fs/src/file/open.rs38
-rw-r--r--third_party/rust/tokio-fs/src/file/open_options.rs103
-rw-r--r--third_party/rust/tokio-fs/src/file/seek.rs37
-rw-r--r--third_party/rust/tokio-fs/src/hard_link.rs54
-rw-r--r--third_party/rust/tokio-fs/src/lib.rs104
-rw-r--r--third_party/rust/tokio-fs/src/metadata.rs45
-rw-r--r--third_party/rust/tokio-fs/src/os/mod.rs6
-rw-r--r--third_party/rust/tokio-fs/src/os/unix.rs55
-rw-r--r--third_party/rust/tokio-fs/src/os/windows/mod.rs7
-rw-r--r--third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs54
-rw-r--r--third_party/rust/tokio-fs/src/os/windows/symlink_file.rs54
-rw-r--r--third_party/rust/tokio-fs/src/read_dir.rs247
-rw-r--r--third_party/rust/tokio-fs/src/read_link.rs46
-rw-r--r--third_party/rust/tokio-fs/src/remove_dir.rs46
-rw-r--r--third_party/rust/tokio-fs/src/remove_file.rs50
-rw-r--r--third_party/rust/tokio-fs/src/rename.rs54
-rw-r--r--third_party/rust/tokio-fs/src/set_permissions.rs48
-rw-r--r--third_party/rust/tokio-fs/src/stderr.rs45
-rw-r--r--third_party/rust/tokio-fs/src/stdin.rs38
-rw-r--r--third_party/rust/tokio-fs/src/stdout.rs44
-rw-r--r--third_party/rust/tokio-fs/src/symlink_metadata.rs49
-rw-r--r--third_party/rust/tokio-fs/tests/file.rs146
33 files changed, 1939 insertions, 0 deletions
diff --git a/third_party/rust/tokio-fs/.cargo-checksum.json b/third_party/rust/tokio-fs/.cargo-checksum.json
new file mode 100644
index 0000000000..7b7e36abd7
--- /dev/null
+++ b/third_party/rust/tokio-fs/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"CHANGELOG.md":"d07abfd675dfa12dda0f46b7ad56fc0f6da677a26a6cfa0531e623e103b68abd","Cargo.toml":"69399fbac7423aa14484b8e89cb8fd187ae7277a024378fd7d74fb7eff033f1c","LICENSE":"4899c290472c872cf8a1904a60e73ec58a1bc1db2e20bc143aa3d1498be49c96","README.md":"2b714a9a29f09a4555b1ee7b7ef27bfd12522c98589eb94f59ef9c315700781b","examples/std-echo.rs":"66927bb61b29565deedbb4fe4a6271a624fed4baf5a5b41bb040059c71b2ad7b","src/create_dir.rs":"e2c4f913fa8d89d10bc2c549dc25c70ec1a119fc7e63909729c19d74a672a80d","src/create_dir_all.rs":"c873c34f00a7075cfeece7fdf76fc85e70871f776ff3811c6d3e8a6b84dd799a","src/file/create.rs":"ad7ef003a65a5bbcd16f28104f19bd7187fa3617c488dd0edb4070074919300b","src/file/metadata.rs":"bddcee02d00a05c272d5d9e2def359f51270d4a25be6630a9c52e3179ed192da","src/file/mod.rs":"fcfb0a882a08600be841d0a40d6746d6c82cf394de8b57e1c21803ea1f1bfcb4","src/file/open.rs":"5012c37d58048606e009bc4b7f7c5095167ce1f5c3dfc9a03e4b1762e83a6de3","src/file/open_options.rs":"0a6ae78653ae200b385b524fe5bbdf069f53a9d7fb087daa11f0bc28759dfc05","src/file/seek.rs":"c1cfe4a228b518e9a7fc3e09567b6ff290b116a7d717f99cdafcd2de13581411","src/hard_link.rs":"3cd1baeed52abc1cb45801d83872ce77df9ea8d037735829b07a1bea07e69fc1","src/lib.rs":"6b8573d70b4b7968d30964803791cf14dfcd4386a74a6170943b3c848f61ab5a","src/metadata.rs":"3882111af4cdbed2eec93ce7fa66b392867833bb55267015e4956d7a2aaa7442","src/os/mod.rs":"9165d5841d1503608049459154c9e2f020ec8d70dde6c00e25833db12addb572","src/os/unix.rs":"44588f808a79a99614812a181ad20d978a1db8b86bf2d95b4fbf77036f15f4ef","src/os/windows/mod.rs":"09c28e0926a2a99ed46fa53f878b1bd84ea73f522acbb40ca63983477922f365","src/os/windows/symlink_dir.rs":"cd41c3d31e9e1a17cf1c21a9c64741d02181242407410ebd65dc4ce81f5c4b8e","src/os/windows/symlink_file.rs":"b9cb16bd85ab90af67baafe6243615b8b3d82348771bd49956a232e9b97b0560","src/read_dir.rs":"138e9d05ec30326ad151b4c1cf1f134f8c3337d9fcf4f0175f51560eb6ee5b97","src/read_link.rs":"ad85fdee77a8ee2ffc1beb35a4a7e7571fc637e1a367d7cf3346ea67673f1edd","src/remove_dir.rs":"21e1e346b53f50d8e8a82c9143bba566a418e09eb13ba8d6c9a6d9155689355b","src/remove_file.rs":"9474d73a6f26ccd1b70da120d2751a1115cc5431983c72f69346b092993b5acc","src/rename.rs":"2eb8fdfcf5b38c059a12abe0443ff65d200b2b44a9b0130b774d417e8949e313","src/set_permissions.rs":"bde74d8d83f8113ef8a1883e1b09a67c26259ddf749f1e11ad2ab2c284222118","src/stderr.rs":"0a84ebdab07500a0b71c03076ccaaf511e093ef77af3b722a0f0acdf91b94034","src/stdin.rs":"ba7b0e4d08dc10743f1139a4aff13d74c564ae9e5dfef8a07388b4b9f75e2c3b","src/stdout.rs":"6f5e807c1bfc90655d364dd2a2d49f8895d86af9ad5cfdf8196a00bdf6d247fb","src/symlink_metadata.rs":"ce4345c5b35f48bcc40b0c0e7c84f3574540a044576fd9837f15724d266480de","tests/file.rs":"1b74b9e1ee6ab62d0db9d900ad497fd42464bb40bcce95453fad67969d9d1ddc"},"package":"b5cbe4ca6e71cb0b62a66e4e6f53a8c06a6eefe46cc5f665ad6f274c9906f135"} \ No newline at end of file
diff --git a/third_party/rust/tokio-fs/CHANGELOG.md b/third_party/rust/tokio-fs/CHANGELOG.md
new file mode 100644
index 0000000000..197d4a8937
--- /dev/null
+++ b/third_party/rust/tokio-fs/CHANGELOG.md
@@ -0,0 +1,18 @@
+# 0.1.3 (August 6, 2018)
+
+* Add async equivalents to most of `std::fs` (#494).
+
+# 0.1.2 (July 11, 2018)
+
+* Add `metadata` and `File::metadata` ([#433](https://github.com/tokio-rs/tokio/pull/433), [#385](https://github.com/tokio-rs/tokio/pull/385))
+* Add `File::seek` ([#434](https://github.com/tokio-rs/tokio/pull/434))
+
+# 0.1.1 (June 13, 2018)
+
+* Add `OpenOptions` ([#390](https://github.com/tokio-rs/tokio/pull/390))
+* Add `into_std` to `File` ([#403](https://github.com/tokio-rs/tokio/pull/403))
+* Use `tokio-codec` in examples
+
+# 0.1.0 (May 2, 2018)
+
+* Initial release
diff --git a/third_party/rust/tokio-fs/Cargo.toml b/third_party/rust/tokio-fs/Cargo.toml
new file mode 100644
index 0000000000..fd5e59434e
--- /dev/null
+++ b/third_party/rust/tokio-fs/Cargo.toml
@@ -0,0 +1,46 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g. crates.io) dependencies
+#
+# If you believe there's an error in this file please file an
+# issue against the rust-lang/cargo repository. If you're
+# editing this file be aware that the upstream Cargo.toml
+# will likely look very different (and much more reasonable)
+
+[package]
+name = "tokio-fs"
+version = "0.1.3"
+authors = ["Carl Lerche <me@carllerche.com>"]
+description = "Filesystem API for Tokio.\n"
+homepage = "https://tokio.rs"
+documentation = "https://docs.rs/tokio-fs/0.1"
+readme = "README.md"
+keywords = ["tokio", "futures", "fs", "file", "async"]
+categories = ["asynchronous", "network-programming", "filesystem"]
+license = "MIT"
+repository = "https://github.com/tokio-rs/tokio"
+[dependencies.futures]
+version = "0.1.21"
+
+[dependencies.tokio-io]
+version = "0.1.6"
+
+[dependencies.tokio-threadpool]
+version = "0.1.3"
+[dev-dependencies.rand]
+version = "0.4.2"
+
+[dev-dependencies.tempdir]
+version = "0.3.7"
+
+[dev-dependencies.tokio]
+version = "0.1.7"
+
+[dev-dependencies.tokio-codec]
+version = "0.1.0"
+
+[dev-dependencies.tokio-io]
+version = "0.1.6"
diff --git a/third_party/rust/tokio-fs/LICENSE b/third_party/rust/tokio-fs/LICENSE
new file mode 100644
index 0000000000..38c1e27b8e
--- /dev/null
+++ b/third_party/rust/tokio-fs/LICENSE
@@ -0,0 +1,25 @@
+Copyright (c) 2018 Tokio Contributors
+
+Permission is hereby granted, free of charge, to any
+person obtaining a copy of this software and associated
+documentation files (the "Software"), to deal in the
+Software without restriction, including without
+limitation the rights to use, copy, modify, merge,
+publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software
+is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice
+shall be included in all copies or substantial portions
+of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
+TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
+SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/tokio-fs/README.md b/third_party/rust/tokio-fs/README.md
new file mode 100644
index 0000000000..f359d7676a
--- /dev/null
+++ b/third_party/rust/tokio-fs/README.md
@@ -0,0 +1,19 @@
+# Tokio FS
+
+Asynchronous filesystem manipulation operations (and stdin, stdout, stderr).
+
+[Documentation](https://tokio-rs.github.io/tokio/tokio_fs/)
+
+## Overview
+
+This crate provides filesystem manipulation facilities for usage with Tokio.
+
+## License
+
+This project is licensed under the [MIT license](LICENSE).
+
+### Contribution
+
+Unless you explicitly state otherwise, any contribution intentionally submitted
+for inclusion in Tokio by you, shall be licensed as MIT, without any additional
+terms or conditions.
diff --git a/third_party/rust/tokio-fs/examples/std-echo.rs b/third_party/rust/tokio-fs/examples/std-echo.rs
new file mode 100644
index 0000000000..83efa66e58
--- /dev/null
+++ b/third_party/rust/tokio-fs/examples/std-echo.rs
@@ -0,0 +1,48 @@
+//! Echo everything received on STDIN to STDOUT.
+#![deny(deprecated, warnings)]
+
+extern crate futures;
+extern crate tokio_fs;
+extern crate tokio_codec;
+extern crate tokio_threadpool;
+
+use tokio_fs::{stdin, stdout, stderr};
+use tokio_codec::{FramedRead, FramedWrite, LinesCodec};
+use tokio_threadpool::Builder;
+
+use futures::{Future, Stream, Sink};
+
+use std::io;
+
+pub fn main() {
+ let pool = Builder::new()
+ .pool_size(1)
+ .build();
+
+ pool.spawn({
+ let input = FramedRead::new(stdin(), LinesCodec::new());
+
+ let output = FramedWrite::new(stdout(), LinesCodec::new())
+ .with(|line: String| {
+ let mut out = "OUT: ".to_string();
+ out.push_str(&line);
+ Ok::<_, io::Error>(out)
+ });
+
+ let error = FramedWrite::new(stderr(), LinesCodec::new())
+ .with(|line: String| {
+ let mut out = "ERR: ".to_string();
+ out.push_str(&line);
+ Ok::<_, io::Error>(out)
+ });
+
+ let dst = output.fanout(error);
+
+ input
+ .forward(dst)
+ .map(|_| ())
+ .map_err(|e| panic!("io error = {:?}", e))
+ });
+
+ pool.shutdown_on_idle().wait().unwrap();
+}
diff --git a/third_party/rust/tokio-fs/src/create_dir.rs b/third_party/rust/tokio-fs/src/create_dir.rs
new file mode 100644
index 0000000000..a174a5d97f
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/create_dir.rs
@@ -0,0 +1,46 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, 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<P: AsRef<Path>>(path: P) -> CreateDirFuture<P> {
+ CreateDirFuture::new(path)
+}
+
+/// Future returned by `create_dir`.
+#[derive(Debug)]
+pub struct CreateDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> CreateDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> CreateDirFuture<P> {
+ CreateDirFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for CreateDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::create_dir(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/create_dir_all.rs b/third_party/rust/tokio-fs/src/create_dir_all.rs
new file mode 100644
index 0000000000..3e32480673
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/create_dir_all.rs
@@ -0,0 +1,47 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Recursively create a directory and all of its parent components if they
+/// are missing.
+///
+/// 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<P: AsRef<Path>>(path: P) -> CreateDirAllFuture<P> {
+ CreateDirAllFuture::new(path)
+}
+
+/// Future returned by `create_dir_all`.
+#[derive(Debug)]
+pub struct CreateDirAllFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> CreateDirAllFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> CreateDirAllFuture<P> {
+ CreateDirAllFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for CreateDirAllFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::create_dir_all(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/create.rs b/third_party/rust/tokio-fs/src/file/create.rs
new file mode 100644
index 0000000000..4027418563
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/create.rs
@@ -0,0 +1,37 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::fs::File as StdFile;
+use std::io;
+use std::path::Path;
+
+/// Future returned by `File::create` and resolves to a `File` instance.
+#[derive(Debug)]
+pub struct CreateFuture<P> {
+ path: P,
+}
+
+impl<P> CreateFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(path: P) -> Self {
+ CreateFuture { path }
+ }
+}
+
+impl<P> Future for CreateFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ type Item = File;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let std = try_ready!(::blocking_io(|| {
+ StdFile::create(&self.path)
+ }));
+
+ let file = File::from_std(std);
+ Ok(file.into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/metadata.rs b/third_party/rust/tokio-fs/src/file/metadata.rs
new file mode 100644
index 0000000000..b55ca103c1
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/metadata.rs
@@ -0,0 +1,39 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::fs::File as StdFile;
+use std::fs::Metadata;
+use std::io;
+
+const POLL_AFTER_RESOLVE: &str = "Cannot poll MetadataFuture after it resolves";
+
+/// Future returned by `File::metadata` and resolves to a `(Metadata, File)` instance.
+#[derive(Debug)]
+pub struct MetadataFuture {
+ file: Option<File>,
+}
+
+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 Item = (File, Metadata);
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let metadata = try_ready!(::blocking_io(|| {
+ StdFile::metadata(self.std())
+ }));
+
+ let file = self.file.take().expect(POLL_AFTER_RESOLVE);
+ Ok((file, metadata).into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/mod.rs b/third_party/rust/tokio-fs/src/file/mod.rs
new file mode 100644
index 0000000000..c3ae431121
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/mod.rs
@@ -0,0 +1,243 @@
+//! Types for working with [`File`].
+//!
+//! [`File`]: file/struct.File.html
+
+mod create;
+mod metadata;
+mod open;
+mod open_options;
+mod seek;
+
+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 tokio_io::{AsyncRead, AsyncWrite};
+
+use futures::Poll;
+
+use std::fs::{File as StdFile, Metadata, Permissions};
+use std::io::{self, Read, Write, Seek};
+use std::path::Path;
+
+/// A reference to an open file on the filesystem.
+///
+/// This is a specialized version of [`std::fs::File`][std] for usage from the
+/// Tokio runtime.
+///
+/// An instance of a `File` can be read and/or written depending on what options
+/// it was opened with. Files also implement Seek to alter the logical cursor
+/// that the file contains internally.
+///
+/// Files are automatically closed when they go out of scope.
+///
+/// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
+#[derive(Debug)]
+pub struct File {
+ std: Option<StdFile>,
+}
+
+impl File {
+ /// Attempts to open a file in read-only mode.
+ ///
+ /// See [`OpenOptions`] for more details.
+ ///
+ /// [`OpenOptions`]: struct.OpenOptions.html
+ ///
+ /// # 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
+ pub fn open<P>(path: P) -> OpenFuture<P>
+ where P: AsRef<Path> + Send + 'static,
+ {
+ OpenOptions::new().read(true).open(path)
+ }
+
+ /// Opens a file in write-only mode.
+ ///
+ /// This function will create a file if it does not exist, and will truncate
+ /// it if it does.
+ ///
+ /// See [`OpenOptions`] for more details.
+ ///
+ /// [`OpenOptions`]: struct.OpenOptions.html
+ ///
+ /// # Errors
+ ///
+ /// `CreateFuture` 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
+ pub fn create<P>(path: P) -> CreateFuture<P>
+ where P: AsRef<Path> + Send + 'static,
+ {
+ CreateFuture::new(path)
+ }
+
+ /// Convert a [`std::fs::File`][std] to a `tokio_fs::File`.
+ ///
+ /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
+ pub(crate) 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<u64, io::Error> {
+ ::blocking_io(|| self.std().seek(pos))
+ }
+
+ /// 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.
+ pub fn seek(self, pos: io::SeekFrom) -> SeekFuture {
+ SeekFuture::new(self, pos)
+ }
+
+ /// Attempts to sync all OS-internal metadata to disk.
+ ///
+ /// This function will attempt to ensure that all in-core data reaches the
+ /// filesystem before returning.
+ pub fn poll_sync_all(&mut self) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().sync_all())
+ }
+
+ /// This function is similar to `poll_sync_all`, except that it may not
+ /// synchronize file metadata to the filesystem.
+ ///
+ /// This is intended for use cases that must synchronize content, but don't
+ /// need the metadata on disk. The goal of this method is to reduce disk
+ /// operations.
+ ///
+ /// Note that some platforms may simply implement this in terms of `poll_sync_all`.
+ pub fn poll_sync_data(&mut self) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().sync_data())
+ }
+
+ /// Truncates or extends the underlying file, updating the size of this file to become size.
+ ///
+ /// If the size is less than the current file's size, then the file will be
+ /// shrunk. If it is greater than the current file's size, then the file
+ /// will be extended to size and have all of the intermediate data filled in
+ /// with 0s.
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the file is not opened for
+ /// writing.
+ pub fn poll_set_len(&mut self, size: u64) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().set_len(size))
+ }
+
+ /// Queries metadata about the underlying file.
+ pub fn metadata(self) -> MetadataFuture {
+ MetadataFuture::new(self)
+ }
+
+ /// Queries metadata about the underlying file.
+ pub fn poll_metadata(&mut self) -> Poll<Metadata, io::Error> {
+ ::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.
+ pub fn poll_try_clone(&mut self) -> Poll<File, io::Error> {
+ ::blocking_io(|| {
+ let std = self.std().try_clone()?;
+ Ok(File::from_std(std))
+ })
+ }
+
+ /// Changes the permissions on the underlying file.
+ ///
+ /// # Platform-specific behavior
+ ///
+ /// This function currently corresponds to the `fchmod` function on Unix and
+ /// the `SetFileInformationByHandle` function on Windows. Note that, this
+ /// [may change in the future][changes].
+ ///
+ /// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the user lacks permission change
+ /// attributes on the underlying file. It may also return an error in other
+ /// os-specific unspecified cases.
+ pub fn poll_set_permissions(&mut self, perm: Permissions) -> Poll<(), io::Error> {
+ ::blocking_io(|| self.std().set_permissions(perm))
+ }
+
+ /// Destructures the `tokio_fs::File` into a [`std::fs::File`][std].
+ ///
+ /// # Panics
+ ///
+ /// This function will panic if `shutdown` has been called.
+ ///
+ /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html
+ 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<usize> {
+ ::would_block(|| self.std().read(buf))
+ }
+}
+
+impl AsyncRead for File {
+ unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
+ false
+ }
+}
+
+impl Write for File {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ ::would_block(|| self.std().write(buf))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ ::would_block(|| self.std().flush())
+ }
+}
+
+impl AsyncWrite for File {
+ fn shutdown(&mut self) -> Poll<(), io::Error> {
+ ::blocking_io(|| {
+ self.std = None;
+ Ok(())
+ })
+ }
+}
+
+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.
+ }
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/open.rs b/third_party/rust/tokio-fs/src/file/open.rs
new file mode 100644
index 0000000000..197ec237af
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/open.rs
@@ -0,0 +1,38 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::fs::OpenOptions as StdOpenOptions;
+use std::io;
+use std::path::Path;
+
+/// Future returned by `File::open` and resolves to a `File` instance.
+#[derive(Debug)]
+pub struct OpenFuture<P> {
+ options: StdOpenOptions,
+ path: P,
+}
+
+impl<P> OpenFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(options: StdOpenOptions, path: P) -> Self {
+ OpenFuture { options, path }
+ }
+}
+
+impl<P> Future for OpenFuture<P>
+where P: AsRef<Path> + Send + 'static,
+{
+ type Item = File;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let std = try_ready!(::blocking_io(|| {
+ self.options.open(&self.path)
+ }));
+
+ let file = File::from_std(std);
+ Ok(file.into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/open_options.rs b/third_party/rust/tokio-fs/src/file/open_options.rs
new file mode 100644
index 0000000000..99cc71c5b0
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/open_options.rs
@@ -0,0 +1,103 @@
+use super::OpenFuture;
+
+use std::convert::From;
+use std::fs::OpenOptions as StdOpenOptions;
+use std::path::Path;
+
+/// Options and flags which can be used to configure how a file is opened.
+///
+/// This is a specialized version of [`std::fs::OpenOptions`] for usage from
+/// the Tokio runtime.
+///
+/// `From<std::fs::OpenOptions>` is implemented for more advanced configuration
+/// than the methods provided here.
+///
+/// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
+#[derive(Clone, Debug)]
+pub struct OpenOptions(StdOpenOptions);
+
+impl OpenOptions {
+ /// Creates a blank new set of options ready for configuration.
+ ///
+ /// All options are initially set to `false`.
+ ///
+ /// # Examples
+ ///
+ /// ```ignore
+ /// use tokio::fs::OpenOptions;
+ ///
+ /// let mut options = OpenOptions::new();
+ /// let future = options.read(true).open("foo.txt");
+ /// ```
+ pub fn new() -> OpenOptions {
+ OpenOptions(StdOpenOptions::new())
+ }
+
+ /// See the underlying [`read`] call for details.
+ ///
+ /// [`read`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.read
+ pub fn read(&mut self, read: bool) -> &mut OpenOptions {
+ self.0.read(read);
+ self
+ }
+
+ /// See the underlying [`write`] call for details.
+ ///
+ /// [`write`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.write
+ pub fn write(&mut self, write: bool) -> &mut OpenOptions {
+ self.0.write(write);
+ self
+ }
+
+ /// See the underlying [`append`] call for details.
+ ///
+ /// [`append`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.append
+ pub fn append(&mut self, append: bool) -> &mut OpenOptions {
+ self.0.append(append);
+ self
+ }
+
+ /// See the underlying [`truncate`] call for details.
+ ///
+ /// [`truncate`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.truncate
+ pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
+ self.0.truncate(truncate);
+ self
+ }
+
+ /// See the underlying [`create`] call for details.
+ ///
+ /// [`create`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create
+ pub fn create(&mut self, create: bool) -> &mut OpenOptions {
+ self.0.create(create);
+ self
+ }
+
+ /// See the underlying [`create_new`] call for details.
+ ///
+ /// [`create_new`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new
+ pub fn create_new(&mut self, create_new: bool) -> &mut OpenOptions {
+ self.0.create_new(create_new);
+ self
+ }
+
+ /// Opens a file at `path` with the options specified by `self`.
+ ///
+ /// # Errors
+ ///
+ /// `OpenOptionsFuture` 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.OpenOptions.html#method.open
+ pub fn open<P>(&self, path: P) -> OpenFuture<P>
+ where P: AsRef<Path> + Send + 'static
+ {
+ OpenFuture::new(self.0.clone(), path)
+ }
+}
+
+impl From<StdOpenOptions> for OpenOptions {
+ fn from(options: StdOpenOptions) -> OpenOptions {
+ OpenOptions(options)
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/file/seek.rs b/third_party/rust/tokio-fs/src/file/seek.rs
new file mode 100644
index 0000000000..0765d3db90
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/file/seek.rs
@@ -0,0 +1,37 @@
+use super::File;
+
+use futures::{Future, Poll};
+
+use std::io;
+
+/// Future returned by `File::seek`.
+#[derive(Debug)]
+pub struct SeekFuture {
+ inner: Option<File>,
+ 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 Item = (File, u64);
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ let pos = try_ready!(
+ self.inner
+ .as_mut()
+ .expect("Cannot poll `SeekFuture` after it resolves")
+ .poll_seek(self.pos)
+ );
+ let inner = self.inner.take().unwrap();
+ Ok((inner, pos).into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/hard_link.rs b/third_party/rust/tokio-fs/src/hard_link.rs
new file mode 100644
index 0000000000..e8ea511520
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/hard_link.rs
@@ -0,0 +1,54 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Creates a new hard link on the filesystem.
+///
+/// The `dst` path will be a link pointing to the `src` path. Note that systems
+/// often require these two paths to both be located on the same filesystem.
+///
+/// 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<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> HardLinkFuture<P, Q> {
+ HardLinkFuture::new(src, dst)
+}
+
+/// Future returned by `hard_link`.
+#[derive(Debug)]
+pub struct HardLinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> HardLinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> HardLinkFuture<P, Q> {
+ HardLinkFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for HardLinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::hard_link(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/lib.rs b/third_party/rust/tokio-fs/src/lib.rs
new file mode 100644
index 0000000000..2beec8c0c6
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/lib.rs
@@ -0,0 +1,104 @@
+//! Asynchronous file and standard stream adaptation.
+//!
+//! This module contains utility methods and adapter types for input/output to
+//! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and
+//! filesystem manipulation, for use within (and only within) a Tokio runtime.
+//!
+//! Tasks run by *worker* threads should not block, as this could delay
+//! servicing reactor events. Portable filesystem operations are blocking,
+//! however. This module offers adapters which use a [`blocking`] annotation
+//! to inform the runtime that a blocking operation is required. When
+//! necessary, this allows the runtime to convert the current thread from a
+//! *worker* to a *backup* thread, where blocking is acceptable.
+//!
+//! ## Usage
+//!
+//! Where possible, users should prefer the provided asynchronous-specific
+//! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll`
+//! type. Adaptions also extend to traits like `std::io::Read` where methods
+//! return `std::io::Result`. Be warned that these adapted methods may return
+//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted
+//! to a *backup* thread immediately. See [tokio-threadpool] for more details
+//! of the threading model and [`blocking`].
+//!
+//! [`blocking`]: https://docs.rs/tokio-threadpool/0.1/tokio_threadpool/fn.blocking.html
+//! [`AsyncRead`]: https://docs.rs/tokio-io/0.1/tokio_io/trait.AsyncRead.html
+//! [tokio-threadpool]: https://docs.rs/tokio-threadpool/0.1/tokio_threadpool
+
+#![deny(missing_docs, missing_debug_implementations, warnings)]
+#![doc(html_root_url = "https://docs.rs/tokio-fs/0.1.3")]
+
+#[macro_use]
+extern crate futures;
+extern crate tokio_io;
+extern crate tokio_threadpool;
+
+mod create_dir;
+mod create_dir_all;
+pub mod file;
+mod hard_link;
+mod metadata;
+pub mod os;
+mod read_dir;
+mod read_link;
+mod remove_dir;
+mod remove_file;
+mod rename;
+mod set_permissions;
+mod stdin;
+mod stdout;
+mod stderr;
+mod symlink_metadata;
+
+pub use create_dir::{create_dir, CreateDirFuture};
+pub use create_dir_all::{create_dir_all, CreateDirAllFuture};
+pub use file::File;
+pub use file::OpenOptions;
+pub use hard_link::{hard_link, HardLinkFuture};
+pub use metadata::{metadata, MetadataFuture};
+pub use read_dir::{read_dir, ReadDirFuture, ReadDir, DirEntry};
+pub use read_link::{read_link, ReadLinkFuture};
+pub use remove_dir::{remove_dir, RemoveDirFuture};
+pub use remove_file::{remove_file, RemoveFileFuture};
+pub use rename::{rename, RenameFuture};
+pub use set_permissions::{set_permissions, SetPermissionsFuture};
+pub use stdin::{stdin, Stdin};
+pub use stdout::{stdout, Stdout};
+pub use stderr::{stderr, Stderr};
+pub use symlink_metadata::{symlink_metadata, SymlinkMetadataFuture};
+
+use futures::Poll;
+use futures::Async::*;
+
+use std::io;
+use std::io::ErrorKind::{Other, WouldBlock};
+
+fn blocking_io<F, T>(f: F) -> Poll<T, io::Error>
+where F: FnOnce() -> io::Result<T>,
+{
+ match tokio_threadpool::blocking(f) {
+ Ok(Ready(Ok(v))) => Ok(v.into()),
+ Ok(Ready(Err(err))) => Err(err),
+ Ok(NotReady) => Ok(NotReady),
+ Err(_) => Err(blocking_err()),
+ }
+}
+
+fn would_block<F, T>(f: F) -> io::Result<T>
+where F: FnOnce() -> io::Result<T>,
+{
+ match tokio_threadpool::blocking(f) {
+ Ok(Ready(Ok(v))) => Ok(v),
+ Ok(Ready(Err(err))) => {
+ debug_assert_ne!(err.kind(), WouldBlock);
+ Err(err)
+ }
+ Ok(NotReady) => Err(WouldBlock.into()),
+ Err(_) => Err(blocking_err()),
+ }
+}
+
+fn blocking_err() -> io::Error {
+ io::Error::new(Other, "`blocking` annotated I/O must be called \
+ from the context of the Tokio runtime.")
+}
diff --git a/third_party/rust/tokio-fs/src/metadata.rs b/third_party/rust/tokio-fs/src/metadata.rs
new file mode 100644
index 0000000000..200d58e080
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/metadata.rs
@@ -0,0 +1,45 @@
+use super::blocking_io;
+
+use futures::{Future, Poll};
+
+use std::fs::{self, Metadata};
+use std::io;
+use std::path::Path;
+
+/// Queries the file system metadata for a path.
+pub fn metadata<P>(path: P) -> MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ MetadataFuture::new(path)
+}
+
+/// Future returned by `metadata`.
+#[derive(Debug)]
+pub struct MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ path: P,
+}
+
+impl<P> MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(path: P) -> Self {
+ Self { path }
+ }
+}
+
+impl<P> Future for MetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ type Item = Metadata;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ blocking_io(|| fs::metadata(&self.path))
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/os/mod.rs b/third_party/rust/tokio-fs/src/os/mod.rs
new file mode 100644
index 0000000000..ae57c48476
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/mod.rs
@@ -0,0 +1,6 @@
+//! OS-specific functionality.
+
+#[cfg(unix)]
+pub mod unix;
+#[cfg(windows)]
+pub mod windows;
diff --git a/third_party/rust/tokio-fs/src/os/unix.rs b/third_party/rust/tokio-fs/src/os/unix.rs
new file mode 100644
index 0000000000..5f8eedeba3
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/unix.rs
@@ -0,0 +1,55 @@
+//! Unix-specific extensions to primitives in the `tokio_fs` module.
+
+use std::io;
+use std::path::Path;
+use std::os::unix::fs;
+
+use futures::{Future, Poll};
+
+/// Creates a new symbolic link on the filesystem.
+///
+/// The `dst` path will be a symbolic link pointing to the `src` path.
+///
+/// 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<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkFuture<P, Q> {
+ SymlinkFuture::new(src, dst)
+}
+
+/// Future returned by `symlink`.
+#[derive(Debug)]
+pub struct SymlinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> SymlinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> SymlinkFuture<P, Q> {
+ SymlinkFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for SymlinkFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::symlink(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/os/windows/mod.rs b/third_party/rust/tokio-fs/src/os/windows/mod.rs
new file mode 100644
index 0000000000..eaeed043eb
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/windows/mod.rs
@@ -0,0 +1,7 @@
+//! Windows-specific extensions for the primitives in the `tokio_fs` module.
+
+mod symlink_dir;
+mod symlink_file;
+
+pub use self::symlink_dir::{symlink_dir, SymlinkDirFuture};
+pub use self::symlink_file::{symlink_file, SymlinkFileFuture};
diff --git a/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs b/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs
new file mode 100644
index 0000000000..9806ff3a3f
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/windows/symlink_dir.rs
@@ -0,0 +1,54 @@
+use std::io;
+use std::path::Path;
+use std::os::windows::fs;
+
+use futures::{Future, Poll};
+
+/// Creates a new directory symlink on the filesystem.
+///
+/// The `dst` path will be a directory symbolic link pointing to the `src`
+/// path.
+///
+/// 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<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkDirFuture<P, Q> {
+ SymlinkDirFuture::new(src, dst)
+}
+
+/// Future returned by `symlink_dir`.
+#[derive(Debug)]
+pub struct SymlinkDirFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> SymlinkDirFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> SymlinkDirFuture<P, Q> {
+ SymlinkDirFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for SymlinkDirFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::symlink_dir(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs b/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs
new file mode 100644
index 0000000000..583b615874
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/os/windows/symlink_file.rs
@@ -0,0 +1,54 @@
+use std::io;
+use std::path::Path;
+use std::os::windows::fs;
+
+use futures::{Future, Poll};
+
+/// Creates a new file symbolic link on the filesystem.
+///
+/// The `dst` path will be a file symbolic link pointing to the `src`
+/// path.
+///
+/// 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<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> SymlinkFileFuture<P, Q> {
+ SymlinkFileFuture::new(src, dst)
+}
+
+/// Future returned by `symlink_file`.
+#[derive(Debug)]
+pub struct SymlinkFileFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ src: P,
+ dst: Q,
+}
+
+impl<P, Q> SymlinkFileFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(src: P, dst: Q) -> SymlinkFileFuture<P, Q> {
+ SymlinkFileFuture {
+ src: src,
+ dst: dst,
+ }
+ }
+}
+
+impl<P, Q> Future for SymlinkFileFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::symlink_file(&self.src, &self.dst) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/read_dir.rs b/third_party/rust/tokio-fs/src/read_dir.rs
new file mode 100644
index 0000000000..3818c7102b
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/read_dir.rs
@@ -0,0 +1,247 @@
+use std::ffi::OsString;
+use std::fs::{self, DirEntry as StdDirEntry, ReadDir as StdReadDir, FileType, Metadata};
+use std::io;
+#[cfg(unix)]
+use std::os::unix::fs::DirEntryExt;
+use std::path::{Path, PathBuf};
+
+use futures::{Future, Poll, Stream};
+
+/// Returns a stream over the entries within a directory.
+///
+/// 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<P>(path: P) -> ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ ReadDirFuture::new(path)
+}
+
+/// Future returned by `read_dir`.
+#[derive(Debug)]
+pub struct ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ path: P,
+}
+
+impl<P> ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static
+{
+ fn new(path: P) -> ReadDirFuture<P> {
+ ReadDirFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for ReadDirFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ type Item = ReadDir;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, io::Error> {
+ ::blocking_io(|| Ok(ReadDir(fs::read_dir(&self.path)?)))
+ }
+}
+
+/// Stream of the entries in a directory.
+///
+/// This stream is returned from the [`read_dir`] function of this module and
+/// will yield instances of [`DirEntry`]. Through a [`DirEntry`]
+/// information like the entry's path and possibly other metadata can be
+/// learned.
+///
+/// # Errors
+///
+/// This [`Stream`] will return an [`Err`] if there's some sort of intermittent
+/// IO error during iteration.
+///
+/// [`read_dir`]: fn.read_dir.html
+/// [`DirEntry`]: struct.DirEntry.html
+/// [`Stream`]: ../futures/stream/trait.Stream.html
+/// [`Err`]: https://doc.rust-lang.org/std/result/enum.Result.html#variant.Err
+#[derive(Debug)]
+pub struct ReadDir(StdReadDir);
+
+impl Stream for ReadDir {
+ type Item = DirEntry;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
+ ::blocking_io(|| {
+ match self.0.next() {
+ Some(Err(err)) => Err(err),
+ Some(Ok(item)) => Ok(Some(DirEntry(item))),
+ None => Ok(None)
+ }
+ })
+ }
+}
+
+/// Entries returned by the [`ReadDir`] stream.
+///
+/// [`ReadDir`]: struct.ReadDir.html
+///
+/// This is a specialized version of [`std::fs::DirEntry`][std] for usage from the
+/// Tokio runtime.
+///
+/// An instance of `DirEntry` represents an entry inside of a directory on the
+/// filesystem. Each entry can be inspected via methods to learn about the full
+/// path or possibly other metadata through per-platform extension traits.
+///
+/// [std]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
+#[derive(Debug)]
+pub struct DirEntry(StdDirEntry);
+
+impl DirEntry {
+ /// Destructures the `tokio_fs::DirEntry` into a [`std::fs::DirEntry`][std].
+ ///
+ /// [std]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
+ pub fn into_std(self) -> StdDirEntry {
+ self.0
+ }
+
+ /// Returns the full path to the file that this entry represents.
+ ///
+ /// The full path is created by joining the original path to `read_dir`
+ /// with the filename of this entry.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ ///
+ /// fn main() {
+ /// let fut = tokio_fs::read_dir(".").flatten_stream().for_each(|dir| {
+ /// println!("{:?}", dir.path());
+ /// Ok(())
+ /// }).map_err(|err| { eprintln!("Error: {:?}", err); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ ///
+ /// This prints output like:
+ ///
+ /// ```text
+ /// "./whatever.txt"
+ /// "./foo.html"
+ /// "./hello_world.rs"
+ /// ```
+ ///
+ /// The exact text, of course, depends on what files you have in `.`.
+ pub fn path(&self) -> PathBuf {
+ self.0.path()
+ }
+
+ /// Returns the bare file name of this directory entry without any other
+ /// leading path component.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ ///
+ /// fn main() {
+ /// 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); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ pub fn file_name(&self) -> OsString {
+ self.0.file_name()
+ }
+
+ /// Return the metadata for the file that this entry points at.
+ ///
+ /// This function will not traverse symlinks if this entry points at a
+ /// symlink.
+ ///
+ /// # Platform-specific behavior
+ ///
+ /// On Windows this function is cheap to call (no extra system calls
+ /// needed), but on Unix platforms this function is the equivalent of
+ /// calling `symlink_metadata` on the path.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ /// use futures::future::poll_fn;
+ ///
+ /// fn main() {
+ /// 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);
+ /// }
+ /// ```
+ pub fn poll_metadata(&self) -> Poll<Metadata, io::Error> {
+ ::blocking_io(|| self.0.metadata())
+ }
+
+ /// Return the file type for the file that this entry points at.
+ ///
+ /// This function will not traverse symlinks if this entry points at a
+ /// symlink.
+ ///
+ /// # Platform-specific behavior
+ ///
+ /// On Windows and most Unix platforms this function is free (no extra
+ /// system calls needed), but some Unix platforms may require the equivalent
+ /// call to `symlink_metadata` to learn about the target file type.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// # extern crate futures;
+ /// # extern crate tokio;
+ /// # extern crate tokio_fs;
+ /// use futures::{Future, Stream};
+ /// use futures::future::poll_fn;
+ ///
+ /// fn main() {
+ /// 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); () });
+ /// tokio::run(fut);
+ /// }
+ /// ```
+ pub fn poll_file_type(&self) -> Poll<FileType, io::Error> {
+ ::blocking_io(|| self.0.file_type())
+ }
+}
+
+#[cfg(unix)]
+impl DirEntryExt for DirEntry {
+ fn ino(&self) -> u64 {
+ self.0.ino()
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/read_link.rs b/third_party/rust/tokio-fs/src/read_link.rs
new file mode 100644
index 0000000000..5e5bf2a30e
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/read_link.rs
@@ -0,0 +1,46 @@
+use std::fs;
+use std::io;
+use std::path::{Path, PathBuf};
+
+use futures::{Future, 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<P: AsRef<Path>>(path: P) -> ReadLinkFuture<P> {
+ ReadLinkFuture::new(path)
+}
+
+/// Future returned by `read_link`.
+#[derive(Debug)]
+pub struct ReadLinkFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> ReadLinkFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> ReadLinkFuture<P> {
+ ReadLinkFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for ReadLinkFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = PathBuf;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::read_link(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/remove_dir.rs b/third_party/rust/tokio-fs/src/remove_dir.rs
new file mode 100644
index 0000000000..5aa73bfb5f
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/remove_dir.rs
@@ -0,0 +1,46 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, 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<P: AsRef<Path>>(path: P) -> RemoveDirFuture<P> {
+ RemoveDirFuture::new(path)
+}
+
+/// Future returned by `remove_dir`.
+#[derive(Debug)]
+pub struct RemoveDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> RemoveDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> RemoveDirFuture<P> {
+ RemoveDirFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for RemoveDirFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::remove_dir(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/remove_file.rs b/third_party/rust/tokio-fs/src/remove_file.rs
new file mode 100644
index 0000000000..f617418579
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/remove_file.rs
@@ -0,0 +1,50 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Removes a file from the filesystem.
+///
+/// Note that there is no
+/// guarantee that the file is immediately deleted (e.g. depending on
+/// platform, other open file descriptors may prevent immediate removal).
+///
+/// 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<P: AsRef<Path>>(path: P) -> RemoveFileFuture<P> {
+ RemoveFileFuture::new(path)
+}
+
+/// Future returned by `remove_file`.
+#[derive(Debug)]
+pub struct RemoveFileFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+}
+
+impl<P> RemoveFileFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P) -> RemoveFileFuture<P> {
+ RemoveFileFuture {
+ path: path,
+ }
+ }
+}
+
+impl<P> Future for RemoveFileFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::remove_file(&self.path) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/rename.rs b/third_party/rust/tokio-fs/src/rename.rs
new file mode 100644
index 0000000000..210f53bb5a
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/rename.rs
@@ -0,0 +1,54 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, Poll};
+
+/// Rename a file or directory to a new name, replacing the original file if
+/// `to` already exists.
+///
+/// This will not work if the new name is on a different mount point.
+///
+/// This is an async version of [`std::fs::rename`][std]
+///
+/// [std]: https://doc.rust-lang.org/std/fs/fn.rename.html
+pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> RenameFuture<P, Q> {
+ RenameFuture::new(from, to)
+}
+
+/// Future returned by `rename`.
+#[derive(Debug)]
+pub struct RenameFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ from: P,
+ to: Q,
+}
+
+impl<P, Q> RenameFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ fn new(from: P, to: Q) -> RenameFuture<P, Q> {
+ RenameFuture {
+ from: from,
+ to: to,
+ }
+ }
+}
+
+impl<P, Q> Future for RenameFuture<P, Q>
+where
+ P: AsRef<Path>,
+ Q: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::rename(&self.from, &self.to) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/set_permissions.rs b/third_party/rust/tokio-fs/src/set_permissions.rs
new file mode 100644
index 0000000000..a850448626
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/set_permissions.rs
@@ -0,0 +1,48 @@
+use std::fs;
+use std::io;
+use std::path::Path;
+
+use futures::{Future, 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<P: AsRef<Path>>(path: P, perm: fs::Permissions) -> SetPermissionsFuture<P> {
+ SetPermissionsFuture::new(path, perm)
+}
+
+/// Future returned by `set_permissions`.
+#[derive(Debug)]
+pub struct SetPermissionsFuture<P>
+where
+ P: AsRef<Path>
+{
+ path: P,
+ perm: fs::Permissions,
+}
+
+impl<P> SetPermissionsFuture<P>
+where
+ P: AsRef<Path>
+{
+ fn new(path: P, perm: fs::Permissions) -> SetPermissionsFuture<P> {
+ SetPermissionsFuture {
+ path: path,
+ perm: perm,
+ }
+ }
+}
+
+impl<P> Future for SetPermissionsFuture<P>
+where
+ P: AsRef<Path>
+{
+ type Item = ();
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ ::blocking_io(|| fs::set_permissions(&self.path, self.perm.clone()) )
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/stderr.rs b/third_party/rust/tokio-fs/src/stderr.rs
new file mode 100644
index 0000000000..cf64390757
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/stderr.rs
@@ -0,0 +1,45 @@
+use tokio_io::{AsyncWrite};
+
+use futures::Poll;
+
+use std::io::{self, Write, Stderr as StdStderr};
+
+/// A handle to the standard error stream of a process.
+///
+/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
+/// writes to `Stderr` must be executed with care.
+///
+/// Created by the [`stderr`] function.
+///
+/// [`stderr`]: fn.stderr.html
+/// [`AsyncWrite`]: trait.AsyncWrite.html
+#[derive(Debug)]
+pub struct Stderr {
+ std: StdStderr,
+}
+
+/// Constructs a new handle to the standard error of the current process.
+///
+/// The returned handle allows writing to standard error from the within the
+/// Tokio runtime.
+pub fn stderr() -> Stderr {
+ let std = io::stderr();
+ Stderr { std }
+}
+
+impl Write for Stderr {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ ::would_block(|| self.std.write(buf))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ ::would_block(|| self.std.flush())
+ }
+}
+
+impl AsyncWrite for Stderr {
+ fn shutdown(&mut self) -> Poll<(), io::Error> {
+ Ok(().into())
+ }
+}
+
diff --git a/third_party/rust/tokio-fs/src/stdin.rs b/third_party/rust/tokio-fs/src/stdin.rs
new file mode 100644
index 0000000000..f41b8dc84c
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/stdin.rs
@@ -0,0 +1,38 @@
+use tokio_io::{AsyncRead};
+
+use std::io::{self, Read, Stdin as StdStdin};
+
+/// A handle to the standard input stream of a process.
+///
+/// The handle implements the [`AsyncRead`] trait, but beware that concurrent
+/// reads of `Stdin` must be executed with care.
+///
+/// Created by the [`stdin`] function.
+///
+/// [`stdin`]: fn.stdin.html
+/// [`AsyncRead`]: trait.AsyncRead.html
+#[derive(Debug)]
+pub struct Stdin {
+ std: StdStdin,
+}
+
+/// Constructs a new handle to the standard input of the current process.
+///
+/// The returned handle allows reading from standard input from the within the
+/// Tokio runtime.
+pub fn stdin() -> Stdin {
+ let std = io::stdin();
+ Stdin { std }
+}
+
+impl Read for Stdin {
+ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+ ::would_block(|| self.std.read(buf))
+ }
+}
+
+impl AsyncRead for Stdin {
+ unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool {
+ false
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/stdout.rs b/third_party/rust/tokio-fs/src/stdout.rs
new file mode 100644
index 0000000000..1c4cd5ad05
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/stdout.rs
@@ -0,0 +1,44 @@
+use tokio_io::{AsyncWrite};
+
+use futures::Poll;
+
+use std::io::{self, Write, Stdout as StdStdout};
+
+/// A handle to the standard output stream of a process.
+///
+/// The handle implements the [`AsyncWrite`] trait, but beware that concurrent
+/// writes to `Stdout` must be executed with care.
+///
+/// Created by the [`stdout`] function.
+///
+/// [`stdout`]: fn.stdout.html
+/// [`AsyncWrite`]: trait.AsyncWrite.html
+#[derive(Debug)]
+pub struct Stdout {
+ std: StdStdout,
+}
+
+/// Constructs a new handle to the standard output of the current process.
+///
+/// The returned handle allows writing to standard out from the within the Tokio
+/// runtime.
+pub fn stdout() -> Stdout {
+ let std = io::stdout();
+ Stdout { std }
+}
+
+impl Write for Stdout {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ ::would_block(|| self.std.write(buf))
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ ::would_block(|| self.std.flush())
+ }
+}
+
+impl AsyncWrite for Stdout {
+ fn shutdown(&mut self) -> Poll<(), io::Error> {
+ Ok(().into())
+ }
+}
diff --git a/third_party/rust/tokio-fs/src/symlink_metadata.rs b/third_party/rust/tokio-fs/src/symlink_metadata.rs
new file mode 100644
index 0000000000..db02769e20
--- /dev/null
+++ b/third_party/rust/tokio-fs/src/symlink_metadata.rs
@@ -0,0 +1,49 @@
+use super::blocking_io;
+
+use futures::{Future, Poll};
+
+use std::fs::{self, Metadata};
+use std::io;
+use std::path::Path;
+
+/// 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<P>(path: P) -> SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ SymlinkMetadataFuture::new(path)
+}
+
+/// Future returned by `symlink_metadata`.
+#[derive(Debug)]
+pub struct SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ path: P,
+}
+
+impl<P> SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ pub(crate) fn new(path: P) -> Self {
+ Self { path }
+ }
+}
+
+impl<P> Future for SymlinkMetadataFuture<P>
+where
+ P: AsRef<Path> + Send + 'static,
+{
+ type Item = Metadata;
+ type Error = io::Error;
+
+ fn poll(&mut self) -> Poll<Self::Item, Self::Error> {
+ blocking_io(|| fs::symlink_metadata(&self.path))
+ }
+}
diff --git a/third_party/rust/tokio-fs/tests/file.rs b/third_party/rust/tokio-fs/tests/file.rs
new file mode 100644
index 0000000000..c8185c1f22
--- /dev/null
+++ b/third_party/rust/tokio-fs/tests/file.rs
@@ -0,0 +1,146 @@
+extern crate futures;
+extern crate rand;
+extern crate tempdir;
+extern crate tokio_fs;
+extern crate tokio_io;
+extern crate tokio_threadpool;
+
+use tokio_fs::*;
+use tokio_io::io;
+use tokio_threadpool::*;
+
+use futures::Future;
+use futures::future::poll_fn;
+use futures::sync::oneshot;
+use rand::{thread_rng, Rng};
+use tempdir::TempDir;
+
+use std::fs::File as StdFile;
+use std::io::{Read, SeekFrom};
+
+#[test]
+fn read_write() {
+ const NUM_CHARS: usize = 16 * 1_024;
+
+ let dir = TempDir::new("tokio-fs-tests").unwrap();
+ let file_path = dir.path().join("read_write.txt");
+
+ let contents: Vec<u8> = thread_rng().gen_ascii_chars()
+ .take(NUM_CHARS)
+ .collect::<String>()
+ .into();
+
+ let pool = Builder::new()
+ .pool_size(1)
+ .build();
+
+ let (tx, rx) = oneshot::channel();
+
+ pool.spawn({
+ let file_path = file_path.clone();
+ let contents = contents.clone();
+
+ File::create(file_path)
+ .and_then(|file| file.metadata())
+ .inspect(|&(_, ref metadata)| assert!(metadata.is_file()))
+ .and_then(move |(file, _)| io::write_all(file, contents))
+ .and_then(|(mut file, _)| {
+ poll_fn(move || file.poll_sync_all())
+ })
+ .then(|res| {
+ let _ = res.unwrap();
+ tx.send(()).unwrap();
+ Ok(())
+ })
+ });
+
+ rx.wait().unwrap();
+
+ let mut file = StdFile::open(&file_path).unwrap();
+
+ let mut dst = vec![];
+ file.read_to_end(&mut dst).unwrap();
+
+ assert_eq!(dst, contents);
+
+ let (tx, rx) = oneshot::channel();
+
+ pool.spawn({
+ File::open(file_path)
+ .and_then(|file| io::read_to_end(file, vec![]))
+ .then(move |res| {
+ let (_, buf) = res.unwrap();
+ assert_eq!(buf, contents);
+ tx.send(()).unwrap();
+ Ok(())
+ })
+ });
+
+ rx.wait().unwrap();
+}
+
+#[test]
+fn metadata() {
+ let dir = TempDir::new("tokio-fs-tests").unwrap();
+ let file_path = dir.path().join("metadata.txt");
+
+ let pool = Builder::new().pool_size(1).build();
+
+ let (tx, rx) = oneshot::channel();
+
+ pool.spawn({
+ let file_path = file_path.clone();
+ let file_path2 = file_path.clone();
+ let file_path3 = file_path.clone();
+
+ tokio_fs::metadata(file_path)
+ .then(|r| {
+ let _ = r.err().unwrap();
+ Ok(())
+ })
+ .and_then(|_| File::create(file_path2))
+ .and_then(|_| tokio_fs::metadata(file_path3))
+ .then(|r| {
+ assert!(r.unwrap().is_file());
+ tx.send(())
+ })
+ });
+
+ rx.wait().unwrap();
+}
+
+#[test]
+fn seek() {
+ let dir = TempDir::new("tokio-fs-tests").unwrap();
+ let file_path = dir.path().join("seek.txt");
+
+ let pool = Builder::new().pool_size(1).build();
+
+ let (tx, rx) = oneshot::channel();
+
+ pool.spawn(
+ OpenOptions::new()
+ .create(true)
+ .read(true)
+ .write(true)
+ .open(file_path)
+ .and_then(|file| io::write_all(file, "Hello, world!"))
+ .and_then(|(file, _)| file.seek(SeekFrom::End(-6)))
+ .and_then(|(file, _)| io::read_exact(file, vec![0; 5]))
+ .and_then(|(file, buf)| {
+ assert_eq!(buf, b"world");
+ file.seek(SeekFrom::Start(0))
+ })
+ .and_then(|(file, _)| io::read_exact(file, vec![0; 5]))
+ .and_then(|(_, buf)| {
+ assert_eq!(buf, b"Hello");
+ Ok(())
+ })
+ .then(|r| {
+ let _ = r.unwrap();
+ tx.send(())
+ }),
+ );
+
+ rx.wait().unwrap();
+}