tokio-fs-0.1.6/Cargo.toml.orig010064400007650000024000000017311343640736300143720ustar0000000000000000[package] name = "tokio-fs" # When releasing to crates.io: # - Update html_root_url. # - Update CHANGELOG.md. # - Update doc URL. # - Cargo.toml # - README.md # - Create "v0.1.x" git tag. version = "0.1.6" authors = ["Carl Lerche "] license = "MIT" readme = "README.md" repository = "https://github.com/tokio-rs/tokio" homepage = "https://tokio.rs" documentation = "https://docs.rs/tokio-fs/0.1.6/tokio_fs" description = """ Filesystem API for Tokio. """ keywords = ["tokio", "futures", "fs", "file", "async"] categories = ["asynchronous", "network-programming", "filesystem"] [dependencies] futures = "0.1.21" tokio-threadpool = { version = "0.1.3", path = "../tokio-threadpool" } tokio-io = { version = "0.1.6", path = "../tokio-io" } [dev-dependencies] rand = "0.6" tempfile = "3" tempdir = "0.3" tokio-io = { version = "0.1.6", path = "../tokio-io" } tokio-codec = { version = "0.1.0", path = "../tokio-codec" } tokio = { version = "0.1.7", path = ".." } tokio-fs-0.1.6/Cargo.toml0000644000000025200000000000000106270ustar00# 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.6" authors = ["Carl Lerche "] description = "Filesystem API for Tokio.\n" homepage = "https://tokio.rs" documentation = "https://docs.rs/tokio-fs/0.1.6/tokio_fs" 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.6" [dev-dependencies.tempdir] version = "0.3" [dev-dependencies.tempfile] version = "3" [dev-dependencies.tokio] version = "0.1.7" [dev-dependencies.tokio-codec] version = "0.1.0" [dev-dependencies.tokio-io] version = "0.1.6" tokio-fs-0.1.6/CHANGELOG.md010064400007650000024000000015201343640736300133100ustar0000000000000000# 0.1.6 (March 1, 2019) ### Added - File::try_clone() (#850). - Async equivalent of read / write file helpers being added to `std` (#896). # 0.1.5 (January 6, 2019) * Add examples to `File` API docs (#786). # 0.1.4 (October 23, 2018) * Provide `File::from_std` (#696). # 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 tokio-fs-0.1.6/examples/std-echo.rs010064400007650000024000000023741343356612400153770ustar0000000000000000//! Echo everything received on STDIN to STDOUT. #![deny(deprecated, warnings)] extern crate futures; extern crate tokio_codec; extern crate tokio_fs; extern crate tokio_threadpool; use tokio_codec::{FramedRead, FramedWrite, LinesCodec}; use tokio_fs::{stderr, stdin, stdout}; use tokio_threadpool::Builder; use futures::{Future, Sink, Stream}; use std::io; pub fn main() -> Result<(), Box> { 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() .map_err(|_| "failed to shutdown the thread pool")?; Ok(()) } tokio-fs-0.1.6/LICENSE010064400007650000024000000020461342041705200124750ustar0000000000000000Copyright (c) 2019 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. tokio-fs-0.1.6/README.md010064400007650000024000000007761343640736300127720ustar0000000000000000# Tokio FS Asynchronous filesystem manipulation operations (and stdin, stdout, stderr). [Documentation](https://docs.rs/tokio-fs/0.1.6/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. tokio-fs-0.1.6/src/create_dir.rs010064400007650000024000000015541343356612400147420ustar0000000000000000use 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>(path: P) -> CreateDirFuture

{ CreateDirFuture::new(path) } /// Future returned by `create_dir`. #[derive(Debug)] pub struct CreateDirFuture

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

CreateDirFuture

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

{ CreateDirFuture { path: path } } } impl

Future for CreateDirFuture

where P: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::create_dir(&self.path)) } } tokio-fs-0.1.6/src/create_dir_all.rs010064400007650000024000000016721343356612400155730ustar0000000000000000use 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>(path: P) -> CreateDirAllFuture

{ CreateDirAllFuture::new(path) } /// Future returned by `create_dir_all`. #[derive(Debug)] pub struct CreateDirAllFuture

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

CreateDirAllFuture

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

{ CreateDirAllFuture { path: path } } } impl

Future for CreateDirAllFuture

where P: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::create_dir_all(&self.path)) } } tokio-fs-0.1.6/src/file/clone.rs010064400007650000024000000015261343334773400146630ustar0000000000000000use super::File; use futures::{Future, Poll}; use std::io; /// 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)] pub struct CloneFuture { file: Option, } impl CloneFuture { pub(crate) fn new(file: File) -> Self { Self { file: Some(file) } } } impl Future for CloneFuture { type Item = (File, File); type Error = (File, io::Error); fn poll(&mut self) -> Poll { self.file .as_mut() .expect("Cannot poll `CloneFuture` after it resolves") .poll_try_clone() .map(|inner| inner.map(|cloned| (self.file.take().unwrap(), cloned))) .map_err(|err| (self.file.take().unwrap(), err)) } } tokio-fs-0.1.6/src/file/create.rs010064400007650000024000000013401343356612400150140ustar0000000000000000use 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

{ path: P, } impl

CreateFuture

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

Future for CreateFuture

where P: AsRef + Send + 'static, { type Item = File; type Error = io::Error; fn poll(&mut self) -> Poll { let std = try_ready!(::blocking_io(|| StdFile::create(&self.path))); let file = File::from_std(std); Ok(file.into()) } } tokio-fs-0.1.6/src/file/metadata.rs010064400007650000024000000016411343356612400153350ustar0000000000000000use 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 `(File, Metadata)` instance. #[derive(Debug)] 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 Item = (File, Metadata); type Error = io::Error; fn poll(&mut self) -> Poll { let metadata = try_ready!(::blocking_io(|| StdFile::metadata(self.std()))); let file = self.file.take().expect(POLL_AFTER_RESOLVE); Ok((file, metadata).into()) } } tokio-fs-0.1.6/src/file/mod.rs010064400007650000024000000413351343356612400143400ustar0000000000000000//! Types for working with [`File`]. //! //! [`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 tokio_io::{AsyncRead, AsyncWrite}; use futures::Poll; use std::fs::{File as StdFile, Metadata, Permissions}; use std::io::{self, Read, Seek, Write}; 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 /// /// # Examples /// /// Create a new file and asynchronously write bytes to it: /// /// ```no_run /// extern crate tokio; /// /// use tokio::prelude::{AsyncWrite, Future}; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` /// /// Read the contents of a file into a buffer /// /// ```no_run /// extern crate tokio; /// /// use tokio::prelude::{AsyncRead, Future}; /// /// fn main() { /// 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)); /// tokio::run(task); /// } /// ``` #[derive(Debug)] pub struct File { std: Option, } 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 /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// fn main() { /// 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); /// }); /// tokio::run(task); /// } /// ``` pub fn open

(path: P) -> OpenFuture

where P: AsRef + 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 /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// fn main() { /// 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); /// }); /// tokio::run(task); /// } /// ``` pub fn create

(path: P) -> CreateFuture

where P: AsRef + Send + 'static, { CreateFuture::new(path) } /// Convert a [`std::fs::File`][std] to a [`tokio_fs::File`][file]. /// /// [std]: https://doc.rust-lang.org/std/fs/struct.File.html /// [file]: struct.File.html /// /// Examples /// ```no_run /// # extern crate tokio; /// use std::fs::File; /// /// fn main() { /// let std_file = 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. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// use std::io::SeekFrom; /// /// fn main() { /// 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 { ::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. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// use std::io::SeekFrom; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` 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. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::{AsyncWrite, Future}; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` 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`. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::{AsyncWrite, Future}; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` 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. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// 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<(), io::Error> { ::blocking_io(|| self.std().set_len(size)) } /// Queries metadata about the underlying file. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// let task = tokio::fs::File::create("foo.txt") /// .and_then(|file| file.metadata()) /// .map(|metadata| { /// println!("{:?}", metadata); /// }).map_err(|err| eprintln!("IO error: {:?}", err)); /// /// tokio::run(task); /// } /// ``` pub fn metadata(self) -> MetadataFuture { MetadataFuture::new(self) } /// Queries metadata about the underlying file. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// 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 { ::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 /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` pub fn poll_try_clone(&mut self) -> Poll { ::blocking_io(|| { let std = self.std().try_clone()?; Ok(File::from_std(std)) }) } /// 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 /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` pub fn try_clone(self) -> CloneFuture { CloneFuture::new(self) } /// 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. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// 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)); /// /// tokio::run(task); /// } /// ``` 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 /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// /// fn main() { /// 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)); /// /// 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 { ::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 { ::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. } } } tokio-fs-0.1.6/src/file/open.rs010064400007650000024000000014451343356612400145200ustar0000000000000000use 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

{ options: StdOpenOptions, path: P, } impl

OpenFuture

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

Future for OpenFuture

where P: AsRef + Send + 'static, { type Item = File; type Error = io::Error; fn poll(&mut self) -> Poll { let std = try_ready!(::blocking_io(|| self.options.open(&self.path))); let file = File::from_std(std); Ok(file.into()) } } tokio-fs-0.1.6/src/file/open_options.rs010064400007650000024000000063551343356612400163000ustar0000000000000000use 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` 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

(&self, path: P) -> OpenFuture

where P: AsRef + Send + 'static, { OpenFuture::new(self.0.clone(), path) } } impl From for OpenOptions { fn from(options: StdOpenOptions) -> OpenOptions { OpenOptions(options) } } tokio-fs-0.1.6/src/file/seek.rs010064400007650000024000000013731343356612400145060ustar0000000000000000use super::File; use futures::{Future, Poll}; use std::io; /// Future returned by `File::seek`. #[derive(Debug)] 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 Item = (File, u64); type Error = io::Error; fn poll(&mut self) -> Poll { 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()) } } tokio-fs-0.1.6/src/hard_link.rs010064400007650000024000000022101343356612400145620ustar0000000000000000use 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, Q: AsRef>(src: P, dst: Q) -> HardLinkFuture { HardLinkFuture::new(src, dst) } /// Future returned by `hard_link`. #[derive(Debug)] 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: src, dst: dst } } } impl Future for HardLinkFuture where P: AsRef, Q: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::hard_link(&self.src, &self.dst)) } } tokio-fs-0.1.6/src/lib.rs010064400007650000024000000072451343640736300134140ustar0000000000000000#![deny(missing_docs, missing_debug_implementations, warnings)] #![doc(html_root_url = "https://docs.rs/tokio-fs/0.1.6")] //! 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 #[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; mod read_dir; mod read_link; mod remove_dir; mod remove_file; mod rename; mod set_permissions; mod stderr; mod stdin; mod stdout; mod symlink_metadata; mod write; 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::{read, ReadFile}; pub use read_dir::{read_dir, DirEntry, ReadDir, ReadDirFuture}; 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 stderr::{stderr, Stderr}; pub use stdin::{stdin, Stdin}; pub use stdout::{stdout, Stdout}; pub use symlink_metadata::{symlink_metadata, SymlinkMetadataFuture}; pub use write::{write, WriteFile}; use futures::Async::*; use futures::Poll; use std::io; use std::io::ErrorKind::{Other, WouldBlock}; fn blocking_io(f: F) -> Poll where F: FnOnce() -> io::Result, { 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: F) -> io::Result where F: FnOnce() -> io::Result, { 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.", ) } tokio-fs-0.1.6/src/metadata.rs010064400007650000024000000015021337762053300144140ustar0000000000000000use 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

(path: P) -> MetadataFuture

where P: AsRef + Send + 'static, { MetadataFuture::new(path) } /// Future returned by `metadata`. #[derive(Debug)] 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 Item = Metadata; type Error = io::Error; fn poll(&mut self) -> Poll { blocking_io(|| fs::metadata(&self.path)) } } tokio-fs-0.1.6/src/os/mod.rs010064400007650000024000000001341337762053300140340ustar0000000000000000//! OS-specific functionality. #[cfg(unix)] pub mod unix; #[cfg(windows)] pub mod windows; tokio-fs-0.1.6/src/os/unix.rs010064400007650000024000000022071343356612400142410ustar0000000000000000//! Unix-specific extensions to primitives in the `tokio_fs` module. use std::io; use std::os::unix::fs; use std::path::Path; 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, 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: src, dst: dst } } } impl Future for SymlinkFuture where P: AsRef, Q: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::symlink(&self.src, &self.dst)) } } tokio-fs-0.1.6/src/os/windows/mod.rs010064400007650000024000000003551337762053300155330ustar0000000000000000//! 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}; tokio-fs-0.1.6/src/os/windows/symlink_dir.rs010064400007650000024000000022051343356612400172720ustar0000000000000000use std::io; use std::os::windows::fs; use std::path::Path; 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, 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: src, dst: dst } } } impl Future for SymlinkDirFuture where P: AsRef, Q: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::symlink_dir(&self.src, &self.dst)) } } tokio-fs-0.1.6/src/os/windows/symlink_file.rs010064400007650000024000000022151343356612400174340ustar0000000000000000use std::io; use std::os::windows::fs; use std::path::Path; 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, 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: src, dst: dst } } } impl Future for SymlinkFileFuture where P: AsRef, Q: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::symlink_file(&self.src, &self.dst)) } } tokio-fs-0.1.6/src/read.rs010064400007650000024000000043231343356612400135510ustar0000000000000000use futures::{Async, Future, Poll}; use std::{io, mem, path::Path}; use tokio_io; use {file, File}; /// Creates a future which will open a file for reading and read the entire /// contents into a buffer and return said buffer. /// /// This is the async equivalent of `std::fs::read`. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// fn main() { /// 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); /// }); /// tokio::run(task); /// } /// ``` pub fn read

(path: P) -> ReadFile

where P: AsRef + Send + '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)] pub struct ReadFile + Send + 'static> { state: State

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

), Metadata(file::MetadataFuture), Read(tokio_io::io::ReadToEnd), } impl + Send + 'static> Future for ReadFile

{ type Item = Vec; type Error = io::Error; fn poll(&mut self) -> Poll { let new_state = match &mut self.state { State::Open(ref mut open_file) => { let file = try_ready!(open_file.poll()); State::Metadata(file.metadata()) } State::Metadata(read_metadata) => { let (file, metadata) = try_ready!(read_metadata.poll()); let buf = Vec::with_capacity(metadata.len() as usize + 1); let read = tokio_io::io::read_to_end(file, buf); State::Read(read) } State::Read(ref mut read) => { let (_, buf) = try_ready!(read.poll()); return Ok(Async::Ready(buf)); } }; mem::replace(&mut self.state, new_state); // Getting here means we transitionsed state. Must poll the new state. self.poll() } } tokio-fs-0.1.6/src/read_dir.rs010064400007650000024000000161331343356612400144110ustar0000000000000000use std::ffi::OsString; use std::fs::{self, DirEntry as StdDirEntry, FileType, Metadata, ReadDir as StdReadDir}; 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

(path: P) -> ReadDirFuture

where P: AsRef + Send + 'static, { ReadDirFuture::new(path) } /// Future returned by `read_dir`. #[derive(Debug)] pub struct ReadDirFuture

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

ReadDirFuture

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

{ ReadDirFuture { path: path } } } impl

Future for ReadDirFuture

where P: AsRef + Send + 'static, { type Item = ReadDir; type Error = io::Error; fn poll(&mut self) -> Poll { ::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, 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 { ::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 { ::blocking_io(|| self.0.file_type()) } } #[cfg(unix)] impl DirEntryExt for DirEntry { fn ino(&self) -> u64 { self.0.ino() } } tokio-fs-0.1.6/src/read_link.rs010064400007650000024000000015771343356612400145760ustar0000000000000000use 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>(path: P) -> ReadLinkFuture

{ ReadLinkFuture::new(path) } /// Future returned by `read_link`. #[derive(Debug)] pub struct ReadLinkFuture

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

ReadLinkFuture

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

{ ReadLinkFuture { path: path } } } impl

Future for ReadLinkFuture

where P: AsRef, { type Item = PathBuf; type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::read_link(&self.path)) } } tokio-fs-0.1.6/src/remove_dir.rs010064400007650000024000000015361343356612400147740ustar0000000000000000use 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>(path: P) -> RemoveDirFuture

{ RemoveDirFuture::new(path) } /// Future returned by `remove_dir`. #[derive(Debug)] pub struct RemoveDirFuture

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

RemoveDirFuture

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

{ RemoveDirFuture { path: path } } } impl

Future for RemoveDirFuture

where P: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::remove_dir(&self.path)) } } tokio-fs-0.1.6/src/remove_file.rs010064400007650000024000000020261343356612400151300ustar0000000000000000use 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>(path: P) -> RemoveFileFuture

{ RemoveFileFuture::new(path) } /// Future returned by `remove_file`. #[derive(Debug)] pub struct RemoveFileFuture

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

RemoveFileFuture

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

{ RemoveFileFuture { path: path } } } impl

Future for RemoveFileFuture

where P: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::remove_file(&self.path)) } } tokio-fs-0.1.6/src/rename.rs010064400007650000024000000021131343356612400141000ustar0000000000000000use 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, Q: AsRef>(from: P, to: Q) -> RenameFuture { RenameFuture::new(from, to) } /// Future returned by `rename`. #[derive(Debug)] 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: from, to: to } } } impl Future for RenameFuture where P: AsRef, Q: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::rename(&self.from, &self.to)) } } tokio-fs-0.1.6/src/set_permissions.rs010064400007650000024000000020731343356612400160640ustar0000000000000000use 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>(path: P, perm: fs::Permissions) -> SetPermissionsFuture

{ SetPermissionsFuture::new(path, perm) } /// Future returned by `set_permissions`. #[derive(Debug)] 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: path, perm: perm, } } } impl

Future for SetPermissionsFuture

where P: AsRef, { type Item = (); type Error = io::Error; fn poll(&mut self) -> Poll { ::blocking_io(|| fs::set_permissions(&self.path, self.perm.clone())) } } tokio-fs-0.1.6/src/stderr.rs010064400007650000024000000020471343356612400141420ustar0000000000000000use tokio_io::AsyncWrite; use futures::Poll; use std::io::{self, Stderr as StdStderr, Write}; /// 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 { ::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()) } } tokio-fs-0.1.6/src/stdin.rs010064400007650000024000000024431343356612400137600ustar0000000000000000use 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. /// /// As an additional caveat, reading from the handle may block the calling /// future indefinitely, if there is not enough data available. This makes this /// handle unsuitable for use in any circumstance where immediate reaction to /// available data is required, e.g. interactive use or when implementing a /// subprocess driven by requests on the standard input. /// /// 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 { ::would_block(|| self.std.read(buf)) } } impl AsyncRead for Stdin { unsafe fn prepare_uninitialized_buffer(&self, _: &mut [u8]) -> bool { false } } tokio-fs-0.1.6/src/stdout.rs010064400007650000024000000020471343356612400141610ustar0000000000000000use tokio_io::AsyncWrite; use futures::Poll; use std::io::{self, Stdout as StdStdout, Write}; /// 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 { ::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()) } } tokio-fs-0.1.6/src/symlink_metadata.rs010064400007650000024000000020151337762053300161620ustar0000000000000000use 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

(path: P) -> SymlinkMetadataFuture

where P: AsRef + Send + 'static, { SymlinkMetadataFuture::new(path) } /// Future returned by `symlink_metadata`. #[derive(Debug)] 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 Item = Metadata; type Error = io::Error; fn poll(&mut self) -> Poll { blocking_io(|| fs::symlink_metadata(&self.path)) } } tokio-fs-0.1.6/src/write.rs010064400007650000024000000043661343356612400137770ustar0000000000000000use futures::{Async, Future, Poll}; use std::{fmt, io, mem, path::Path}; use tokio_io; use {file, File}; /// Creates a future that will open a file for writing and write the entire /// contents of `contents` to it. /// /// This is the async equivalent of `std::fs::write`. /// /// # Examples /// /// ```no_run /// # extern crate tokio; /// use tokio::prelude::Future; /// fn main() { /// 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); /// }); /// tokio::run(task); /// } /// ``` pub fn write>(path: P, contents: C) -> WriteFile where P: AsRef + Send + '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)] pub struct WriteFile + Send + 'static, C: AsRef<[u8]>> { state: State, } #[derive(Debug)] enum State + Send + 'static, C: AsRef<[u8]>> { Create(file::CreateFuture

, Option), Write(tokio_io::io::WriteAll), } impl + Send + 'static, C: AsRef<[u8]> + fmt::Debug> Future for WriteFile { type Item = C; type Error = io::Error; fn poll(&mut self) -> Poll { let new_state = match &mut self.state { State::Create(ref mut create_file, contents) => { let file = try_ready!(create_file.poll()); let write = tokio_io::io::write_all(file, contents.take().unwrap()); State::Write(write) } State::Write(ref mut write) => { let (_, contents) = try_ready!(write.poll()); return Ok(Async::Ready(contents)); } }; mem::replace(&mut self.state, new_state); // We just entered the Write state, need to poll it before returning. self.poll() } } tokio-fs-0.1.6/tests/dir.rs010064400007650000024000000031361342041704000137540ustar0000000000000000extern crate futures; extern crate tempdir; extern crate tokio_fs; use futures::{Future, Stream}; use std::fs; use std::sync::{Arc, Mutex}; use tempdir::TempDir; use tokio_fs::*; mod pool; #[test] fn create() { let base_dir = TempDir::new("base").unwrap(); let new_dir = base_dir.path().join("foo"); pool::run({ create_dir(new_dir.clone()) }); assert!(new_dir.is_dir()); } #[test] fn create_all() { let base_dir = TempDir::new("base").unwrap(); let new_dir = base_dir.path().join("foo").join("bar"); pool::run({ create_dir_all(new_dir.clone()) }); assert!(new_dir.is_dir()); } #[test] fn remove() { let base_dir = TempDir::new("base").unwrap(); let new_dir = base_dir.path().join("foo"); fs::create_dir(new_dir.clone()).unwrap(); pool::run({ remove_dir(new_dir.clone()) }); assert!(!new_dir.exists()); } #[test] fn read() { let base_dir = TempDir::new("base").unwrap(); let p = base_dir.path(); fs::create_dir(p.join("aa")).unwrap(); fs::create_dir(p.join("bb")).unwrap(); fs::create_dir(p.join("cc")).unwrap(); let files = Arc::new(Mutex::new(Vec::new())); let f = files.clone(); let p = p.to_path_buf(); pool::run({ read_dir(p).flatten_stream().for_each(move |e| { let s = e.file_name().to_str().unwrap().to_string(); f.lock().unwrap().push(s); Ok(()) }) }); let mut files = files.lock().unwrap(); files.sort(); // because the order is not guaranteed assert_eq!( *files, vec!["aa".to_string(), "bb".to_string(), "cc".to_string()] ); } tokio-fs-0.1.6/tests/file.rs010064400007650000024000000114341343343712600141300ustar0000000000000000extern crate futures; extern crate rand; extern crate tempfile; extern crate tokio_fs; extern crate tokio_io; use tokio_fs::*; use tokio_io::io; use futures::future::poll_fn; use futures::Future; use rand::{distributions, thread_rng, Rng}; use tempfile::Builder as TmpBuilder; use std::fs; use std::io::SeekFrom; mod pool; #[test] fn read_write() { const NUM_CHARS: usize = 16 * 1_024; let dir = TmpBuilder::new() .prefix("tokio-fs-tests") .tempdir() .unwrap(); let file_path = dir.path().join("read_write.txt"); let contents: Vec = thread_rng() .sample_iter(&distributions::Alphanumeric) .take(NUM_CHARS) .collect::() .into(); pool::run({ 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(); Ok(()) }) }); let dst = fs::read(&file_path).unwrap(); assert_eq!(dst, contents); pool::run({ File::open(file_path) .and_then(|file| io::read_to_end(file, vec![])) .then(move |res| { let (_, buf) = res.unwrap(); assert_eq!(buf, contents); Ok(()) }) }); } #[test] fn read_write_helpers() { const NUM_CHARS: usize = 16 * 1_024; let dir = TmpBuilder::new() .prefix("tokio-fs-tests") .tempdir() .unwrap(); let file_path = dir.path().join("read_write_all.txt"); let contents: Vec = thread_rng() .sample_iter(&distributions::Alphanumeric) .take(NUM_CHARS) .collect::() .into(); pool::run(write(file_path.clone(), contents.clone()).then(|res| { let _ = res.unwrap(); Ok(()) })); let dst = fs::read(&file_path).unwrap(); assert_eq!(dst, contents); pool::run({ read(file_path).then(move |res| { let buf = res.unwrap(); assert_eq!(buf, contents); Ok(()) }) }); } #[test] fn metadata() { let dir = TmpBuilder::new() .prefix("tokio-fs-tests") .tempdir() .unwrap(); let file_path = dir.path().join("metadata.txt"); pool::run({ 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()); Ok(()) }) }); } #[test] fn seek() { let dir = TmpBuilder::new() .prefix("tokio-fs-tests") .tempdir() .unwrap(); let file_path = dir.path().join("seek.txt"); pool::run({ 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(); Ok(()) }) }); } #[test] fn clone() { use std::io::prelude::*; let dir = TmpBuilder::new() .prefix("tokio-fs-tests") .tempdir() .unwrap(); let file_path = dir.path().join("clone.txt"); pool::run( File::create(file_path.clone()) .and_then(|file| { file.try_clone() .map_err(|(_file, err)| err) .and_then(|(file, clone)| { io::write_all(file, "clone ") .and_then(|_| io::write_all(clone, "successful")) }) }) .then(|res| { let _ = res.unwrap(); Ok(()) }), ); let mut file = std::fs::File::open(&file_path).unwrap(); let mut dst = vec![]; file.read_to_end(&mut dst).unwrap(); assert_eq!(dst, b"clone successful") } tokio-fs-0.1.6/tests/link.rs010064400007650000024000000027701342041704000141360ustar0000000000000000extern crate futures; extern crate tempdir; extern crate tokio_fs; use futures::Future; use std::fs; use std::io::prelude::*; use std::io::BufReader; use tempdir::TempDir; use tokio_fs::*; mod pool; #[test] fn test_hard_link() { let dir = TempDir::new("base").unwrap(); let src = dir.path().join("src.txt"); let dst = dir.path().join("dst.txt"); { let mut file = fs::File::create(&src).unwrap(); file.write_all(b"hello").unwrap(); } pool::run({ hard_link(src, dst.clone()) }); let mut content = String::new(); { let file = fs::File::open(dst).unwrap(); let mut reader = BufReader::new(file); reader.read_to_string(&mut content).unwrap(); } assert!(content == "hello"); } #[cfg(unix)] #[test] fn test_symlink() { let dir = TempDir::new("base").unwrap(); let src = dir.path().join("src.txt"); let dst = dir.path().join("dst.txt"); { let mut file = fs::File::create(&src).unwrap(); file.write_all(b"hello").unwrap(); } pool::run({ os::unix::symlink(src.clone(), dst.clone()) }); let mut content = String::new(); { let file = fs::File::open(dst.clone()).unwrap(); let mut reader = BufReader::new(file); reader.read_to_string(&mut content).unwrap(); } assert!(content == "hello"); pool::run({ read_link(dst.clone()).map(move |x| assert!(x == src)) }); pool::run({ symlink_metadata(dst.clone()).map(move |x| assert!(x.file_type().is_symlink())) }); } tokio-fs-0.1.6/tests/pool/mod.rs010064400007650000024000000006271342041704000147300ustar0000000000000000extern crate futures; extern crate tokio_threadpool; use self::tokio_threadpool::Builder; use futures::sync::oneshot; use futures::Future; use std::io; pub fn run(f: F) where F: Future + Send + 'static, { let pool = Builder::new().pool_size(1).build(); let (tx, rx) = oneshot::channel::<()>(); pool.spawn(f.then(|_| tx.send(()))); rx.wait().unwrap() } tokio-fs-0.1.6/.cargo_vcs_info.json0000644000000001120000000000000126240ustar00{ "git": { "sha1": "e28856cffe00aa3f0c30292a91e36adab422668c" } }