forked from mirror/async-std
190: Clean up the fs module and a few other places r=stjepang a=stjepang Just a cleanup for various pieces of documentation, mainly around the `lib.rs` docs, the prelude, and the `fs` module. Some small bugs are also fixed along the way. This PR is the first one in a series of review PRs that I will be submitting before the upcoming 1.0 release. 200: expose IoSlice, IoSliceMut r=stjepang a=yoshuawuyts Exposes `io::IoSlice` and `io::IoSliceMut`. Given we're returning these from `read_vectored` and `write_vectored` it might make sense to just include them as part of our re-exports. Thanks! Ref #131. Co-authored-by: Stjepan Glavina <stjepang@gmail.com> Co-authored-by: Yoshua Wuyts <yoshuawuyts@gmail.com>
This commit is contained in:
commit
ee31f68e80
42 changed files with 843 additions and 411 deletions
|
@ -3,7 +3,8 @@ name = "async-std"
|
|||
version = "0.99.5"
|
||||
authors = [
|
||||
"Stjepan Glavina <stjepang@gmail.com>",
|
||||
"The async-std Project Developers",
|
||||
"Yoshua Wuyts <yoshuawuyts@gmail.com>",
|
||||
"Contributors to async-std",
|
||||
]
|
||||
edition = "2018"
|
||||
license = "Apache-2.0/MIT"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
# Async version of Rust's standard library
|
||||
# Async version of the Rust standard library
|
||||
|
||||
[![Build Status](https://travis-ci.com/async-rs/async-std.svg?branch=master)](https://travis-ci.com/async-rs/async-std)
|
||||
[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](https://github.com/async-rs/async-std)
|
||||
|
|
|
@ -13,8 +13,9 @@ fn main() -> io::Result<()> {
|
|||
task::block_on(async {
|
||||
let mut dir = fs::read_dir(&path).await?;
|
||||
|
||||
while let Some(entry) = dir.next().await {
|
||||
println!("{}", entry?.file_name().to_string_lossy());
|
||||
while let Some(res) = dir.next().await {
|
||||
let entry = res?;
|
||||
println!("{}", entry.file_name().to_string_lossy());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::io;
|
||||
|
@ -15,10 +14,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` does not exist.
|
||||
/// * A non-final component in path is not a directory.
|
||||
/// * `path` does not point to an existing file or directory.
|
||||
/// * A non-final component in `path` is not a directory.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -33,5 +33,5 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::canonicalize(path) }).await
|
||||
blocking::spawn(async move { std::fs::canonicalize(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,28 +1,32 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Copies the contents and permissions of one file to another.
|
||||
/// Copies the contents and permissions of a file to a new location.
|
||||
///
|
||||
/// On success, the total number of bytes copied is returned and equals the length of the `from`
|
||||
/// file.
|
||||
/// On success, the total number of bytes copied is returned and equals the length of the `to` file
|
||||
/// after this operation.
|
||||
///
|
||||
/// The old contents of `to` will be overwritten. If `from` and `to` both point to the same file,
|
||||
/// then the file will likely get truncated by this operation.
|
||||
/// then the file will likely get truncated as a result of this operation.
|
||||
///
|
||||
/// If you're working with open [`File`]s and want to copy contents through those types, use the
|
||||
/// [`io::copy`] function.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::copy`].
|
||||
///
|
||||
/// [`File`]: struct.File.html
|
||||
/// [`io::copy`]: ../io/fn.copy.html
|
||||
/// [`std::fs::copy`]: https://doc.rust-lang.org/std/fs/fn.copy.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * The `from` path is not a file.
|
||||
/// * The `from` file does not exist.
|
||||
/// * The current process lacks permissions to access `from` or write `to`.
|
||||
/// * `from` does not point to an existing file.
|
||||
/// * The current process lacks permissions to read `from` or write `to`.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -31,12 +35,12 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// let bytes_copied = fs::copy("a.txt", "b.txt").await?;
|
||||
/// let num_bytes = fs::copy("a.txt", "b.txt").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn copy<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<u64> {
|
||||
let from = from.as_ref().to_owned();
|
||||
let to = to.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::copy(&from, &to) }).await
|
||||
blocking::spawn(async move { std::fs::copy(&from, &to) }).await
|
||||
}
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Creates a new, empty directory.
|
||||
/// Creates a new directory.
|
||||
///
|
||||
/// Note that this function will only create the final directory in `path`. If you want to create
|
||||
/// all of its missing parent directories too, use the [`create_dir_all`] function instead.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::create_dir`].
|
||||
///
|
||||
/// [`create_dir_all`]: fn.create_dir_all.html
|
||||
/// [`std::fs::create_dir`]: https://doc.rust-lang.org/std/fs/fn.create_dir.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` already exists.
|
||||
/// * A parent of the given path does not exist.
|
||||
/// * The current process lacks permissions to create directory at `path`.
|
||||
/// * `path` already points to an existing file or directory.
|
||||
/// * A parent directory in `path` does not exist.
|
||||
/// * The current process lacks permissions to create the directory.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -25,11 +29,11 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// fs::create_dir("./some/dir").await?;
|
||||
/// fs::create_dir("./some/directory").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::create_dir(path) }).await
|
||||
blocking::spawn(async move { std::fs::create_dir(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Creates a new, empty directory and all of its parents if they are missing.
|
||||
/// Creates a new directory and all of its parents if they are missing.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::create_dir_all`].
|
||||
///
|
||||
|
@ -12,10 +11,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * The parent directories do not exists and couldn't be created.
|
||||
/// * The current process lacks permissions to create directory at `path`.
|
||||
/// * `path` already points to an existing file or directory.
|
||||
/// * The current process lacks permissions to create the directory or its missing parents.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -24,11 +24,11 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// fs::create_dir_all("./some/dir").await?;
|
||||
/// fs::create_dir_all("./some/directory").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::create_dir_all(path) }).await
|
||||
blocking::spawn(async move { std::fs::create_dir_all(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
@ -7,21 +6,28 @@ use crate::future::Future;
|
|||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// A builder for creating directories in various manners.
|
||||
/// A builder for creating directories with configurable options.
|
||||
///
|
||||
/// For Unix-specific options, import the [`os::unix::fs::DirBuilderExt`] trait.
|
||||
///
|
||||
/// This type is an async version of [`std::fs::DirBuilder`].
|
||||
///
|
||||
/// [`os::unix::fs::DirBuilderExt`]: ../os/unix/fs/trait.DirBuilderExt.html
|
||||
/// [`std::fs::DirBuilder`]: https://doc.rust-lang.org/std/fs/struct.DirBuilder.html
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {
|
||||
/// Set to `true` if non-existent parent directories should be created.
|
||||
recursive: bool,
|
||||
|
||||
/// Unix mode for newly created directories.
|
||||
#[cfg(unix)]
|
||||
mode: Option<u32>,
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
/// Creates a new builder with [`recursive`] set to `false`.
|
||||
/// Creates a blank set of options.
|
||||
///
|
||||
/// The [`recursive`] option is initially set to `false`.
|
||||
///
|
||||
/// [`recursive`]: #method.recursive
|
||||
///
|
||||
|
@ -33,25 +39,24 @@ impl DirBuilder {
|
|||
/// let builder = DirBuilder::new();
|
||||
/// ```
|
||||
pub fn new() -> DirBuilder {
|
||||
#[cfg(not(unix))]
|
||||
let builder = DirBuilder { recursive: false };
|
||||
|
||||
#[cfg(unix)]
|
||||
let builder = DirBuilder {
|
||||
recursive: false,
|
||||
mode: None,
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
let builder = DirBuilder { recursive: false };
|
||||
|
||||
builder
|
||||
}
|
||||
|
||||
/// Sets the option for recursive mode.
|
||||
///
|
||||
/// This option, when `true`, means that all parent directories should be created recursively
|
||||
/// if they don't exist. Parents are created with the same security settings and permissions as
|
||||
/// the final directory.
|
||||
/// When set to `true`, this option means all parent directories should be created recursively
|
||||
/// if they don't exist. Parents are created with the same permissions as the final directory.
|
||||
///
|
||||
/// This option defaults to `false`.
|
||||
/// This option is initially set to `false`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -70,6 +75,14 @@ impl DirBuilder {
|
|||
///
|
||||
/// It is considered an error if the directory already exists unless recursive mode is enabled.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` already points to an existing file or directory.
|
||||
/// * The current process lacks permissions to create the directory or its missing parents.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -79,13 +92,13 @@ impl DirBuilder {
|
|||
///
|
||||
/// DirBuilder::new()
|
||||
/// .recursive(true)
|
||||
/// .create("/tmp/foo/bar/baz")
|
||||
/// .create("./some/directory")
|
||||
/// .await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn create<P: AsRef<Path>>(&self, path: P) -> impl Future<Output = io::Result<()>> {
|
||||
let mut builder = fs::DirBuilder::new();
|
||||
let mut builder = std::fs::DirBuilder::new();
|
||||
builder.recursive(self.recursive);
|
||||
|
||||
#[cfg(unix)]
|
||||
|
|
|
@ -1,45 +1,28 @@
|
|||
use std::ffi::OsString;
|
||||
use std::fs;
|
||||
use std::fmt;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use crate::fs::{FileType, Metadata};
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// An entry inside a directory.
|
||||
/// An entry in a directory.
|
||||
///
|
||||
/// An instance of `DirEntry` represents an entry inside a directory on the filesystem. Each entry
|
||||
/// carriers additional information like the full path or metadata.
|
||||
/// A stream of entries in a directory is returned by [`read_dir`].
|
||||
///
|
||||
/// This type is an async version of [`std::fs::DirEntry`].
|
||||
///
|
||||
/// [`read_dir`]: fn.read_dir.html
|
||||
/// [`std::fs::DirEntry`]: https://doc.rust-lang.org/std/fs/struct.DirEntry.html
|
||||
#[derive(Debug)]
|
||||
pub struct DirEntry {
|
||||
/// The inner synchronous `DirEntry`.
|
||||
inner: Arc<fs::DirEntry>,
|
||||
|
||||
#[cfg(unix)]
|
||||
ino: u64,
|
||||
}
|
||||
pub struct DirEntry(Arc<std::fs::DirEntry>);
|
||||
|
||||
impl DirEntry {
|
||||
/// Creates an asynchronous `DirEntry` from a synchronous handle.
|
||||
pub(crate) fn new(inner: fs::DirEntry) -> DirEntry {
|
||||
#[cfg(unix)]
|
||||
let dir_entry = DirEntry {
|
||||
ino: inner.ino(),
|
||||
inner: Arc::new(inner),
|
||||
};
|
||||
|
||||
#[cfg(windows)]
|
||||
let dir_entry = DirEntry {
|
||||
inner: Arc::new(inner),
|
||||
};
|
||||
|
||||
dir_entry
|
||||
/// Creates an asynchronous `DirEntry` from a synchronous one.
|
||||
pub(crate) fn new(inner: std::fs::DirEntry) -> DirEntry {
|
||||
DirEntry(Arc::new(inner))
|
||||
}
|
||||
|
||||
/// Returns the full path to this entry.
|
||||
|
@ -59,20 +42,33 @@ impl DirEntry {
|
|||
///
|
||||
/// let mut dir = fs::read_dir(".").await?;
|
||||
///
|
||||
/// while let Some(entry) = dir.next().await {
|
||||
/// let entry = entry?;
|
||||
/// while let Some(res) = dir.next().await {
|
||||
/// let entry = res?;
|
||||
/// println!("{:?}", entry.path());
|
||||
/// }
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.inner.path()
|
||||
self.0.path()
|
||||
}
|
||||
|
||||
/// Returns the metadata for this entry.
|
||||
/// Reads the metadata for this entry.
|
||||
///
|
||||
/// This function will not traverse symlinks if this entry points at a symlink.
|
||||
/// This function will traverse symbolic links to read the metadata.
|
||||
///
|
||||
/// If you want to read metadata without following symbolic links, use [`symlink_metadata`]
|
||||
/// instead.
|
||||
///
|
||||
/// [`symlink_metadata`]: fn.symlink_metadata.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * This entry does not point to an existing file or directory anymore.
|
||||
/// * The current process lacks permissions to read the metadata.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -84,21 +80,33 @@ impl DirEntry {
|
|||
///
|
||||
/// let mut dir = fs::read_dir(".").await?;
|
||||
///
|
||||
/// while let Some(entry) = dir.next().await {
|
||||
/// let entry = entry?;
|
||||
/// while let Some(res) = dir.next().await {
|
||||
/// let entry = res?;
|
||||
/// println!("{:?}", entry.metadata().await?);
|
||||
/// }
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn metadata(&self) -> io::Result<fs::Metadata> {
|
||||
let inner = self.inner.clone();
|
||||
pub async fn metadata(&self) -> io::Result<Metadata> {
|
||||
let inner = self.0.clone();
|
||||
blocking::spawn(async move { inner.metadata() }).await
|
||||
}
|
||||
|
||||
/// Returns the file type for this entry.
|
||||
/// Reads the file type for this entry.
|
||||
///
|
||||
/// This function will not traverse symlinks if this entry points at a symlink.
|
||||
/// This function will not traverse symbolic links if this entry points at one.
|
||||
///
|
||||
/// If you want to read metadata with following symbolic links, use [`metadata`] instead.
|
||||
///
|
||||
/// [`metadata`]: #method.metadata
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * This entry does not point to an existing file or directory anymore.
|
||||
/// * The current process lacks permissions to read this entry's metadata.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -110,15 +118,15 @@ impl DirEntry {
|
|||
///
|
||||
/// let mut dir = fs::read_dir(".").await?;
|
||||
///
|
||||
/// while let Some(entry) = dir.next().await {
|
||||
/// let entry = entry?;
|
||||
/// while let Some(res) = dir.next().await {
|
||||
/// let entry = res?;
|
||||
/// println!("{:?}", entry.file_type().await?);
|
||||
/// }
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn file_type(&self) -> io::Result<fs::FileType> {
|
||||
let inner = self.inner.clone();
|
||||
pub async fn file_type(&self) -> io::Result<FileType> {
|
||||
let inner = self.0.clone();
|
||||
blocking::spawn(async move { inner.file_type() }).await
|
||||
}
|
||||
|
||||
|
@ -134,15 +142,21 @@ impl DirEntry {
|
|||
///
|
||||
/// let mut dir = fs::read_dir(".").await?;
|
||||
///
|
||||
/// while let Some(entry) = dir.next().await {
|
||||
/// let entry = entry?;
|
||||
/// println!("{:?}", entry.file_name());
|
||||
/// while let Some(res) = dir.next().await {
|
||||
/// let entry = res?;
|
||||
/// println!("{}", entry.file_name().to_string_lossy());
|
||||
/// }
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.inner.file_name()
|
||||
self.0.file_name()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for DirEntry {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_tuple("DirEntry").field(&self.path()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -159,7 +173,7 @@ cfg_if! {
|
|||
if #[cfg(any(unix, feature = "docs"))] {
|
||||
impl DirEntryExt for DirEntry {
|
||||
fn ino(&self) -> u64 {
|
||||
self.ino
|
||||
self.0.ino()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
202
src/fs/file.rs
202
src/fs/file.rs
|
@ -1,9 +1,7 @@
|
|||
//! Async file implementation.
|
||||
|
||||
use std::cell::UnsafeCell;
|
||||
use std::cmp;
|
||||
use std::fs;
|
||||
use std::io::{Read as _, Seek, SeekFrom, Write as _};
|
||||
use std::fmt;
|
||||
use std::io::{Read as _, Seek as _, Write as _};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::path::Path;
|
||||
use std::pin::Pin;
|
||||
|
@ -13,22 +11,22 @@ use std::sync::{Arc, Mutex};
|
|||
use cfg_if::cfg_if;
|
||||
use futures_io::{AsyncRead, AsyncSeek, AsyncWrite, Initializer};
|
||||
|
||||
use crate::fs::{Metadata, Permissions};
|
||||
use crate::future;
|
||||
use crate::io::{self, Write};
|
||||
use crate::io::{self, SeekFrom, Write};
|
||||
use crate::task::{self, blocking, Context, Poll, Waker};
|
||||
|
||||
/// A reference to a file on the filesystem.
|
||||
/// An open file on the filesystem.
|
||||
///
|
||||
/// An instance of a `File` can be read and/or written depending on what options it was opened
|
||||
/// with.
|
||||
/// Depending on what options the file was opened with, this type can be used for reading and/or
|
||||
/// writing.
|
||||
///
|
||||
/// Files are automatically closed when they go out of scope. Errors detected on closing are
|
||||
/// ignored by the implementation of `Drop`. Use the method [`sync_all`] if these errors must be
|
||||
/// manually handled.
|
||||
/// Files are automatically closed when they get dropped and any errors detected on closing are
|
||||
/// ignored. Use the [`sync_all`] method before dropping a file if such errors need to be handled.
|
||||
///
|
||||
/// This type is an async version of [`std::fs::File`].
|
||||
///
|
||||
/// [`sync_all`]: struct.File.html#method.sync_all
|
||||
/// [`sync_all`]: #method.sync_all
|
||||
/// [`std::fs::File`]: https://doc.rust-lang.org/std/fs/struct.File.html
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -47,7 +45,7 @@ use crate::task::{self, blocking, Context, Poll, Waker};
|
|||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
///
|
||||
/// Read the contents of a file into a `Vec<u8>`:
|
||||
/// Read the contents of a file into a vector of bytes:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
|
@ -61,23 +59,30 @@ use crate::task::{self, blocking, Context, Poll, Waker};
|
|||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct File {
|
||||
file: Arc<fs::File>,
|
||||
/// A reference to the inner file.
|
||||
file: Arc<std::fs::File>,
|
||||
|
||||
/// The state of the file protected by an async lock.
|
||||
lock: Lock<State>,
|
||||
}
|
||||
|
||||
impl File {
|
||||
/// Opens a file in read-only mode.
|
||||
///
|
||||
/// See the [`OpenOptions::open`] method for more details.
|
||||
/// See the [`OpenOptions::open`] function for more options.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if `path` does not already exist.
|
||||
/// Other errors may also be returned according to [`OpenOptions::open`].
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// [`OpenOptions::open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
|
||||
/// * `path` does not point to an existing file.
|
||||
/// * The current process lacks permissions to read the file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// For more details, see the list of errors documented by [`OpenOptions::open`].
|
||||
///
|
||||
/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -92,7 +97,7 @@ impl File {
|
|||
/// ```
|
||||
pub async fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
|
||||
let path = path.as_ref().to_owned();
|
||||
let file = blocking::spawn(async move { fs::File::open(&path) }).await?;
|
||||
let file = blocking::spawn(async move { std::fs::File::open(&path) }).await?;
|
||||
Ok(file.into())
|
||||
}
|
||||
|
||||
|
@ -100,9 +105,19 @@ impl File {
|
|||
///
|
||||
/// This function will create a file if it does not exist, and will truncate it if it does.
|
||||
///
|
||||
/// See the [`OpenOptions::open`] function for more details.
|
||||
/// See the [`OpenOptions::open`] function for more options.
|
||||
///
|
||||
/// [`OpenOptions::open`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * The file's parent directory does not exist.
|
||||
/// * The current process lacks permissions to write to the file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// For more details, see the list of errors documented by [`OpenOptions::open`].
|
||||
///
|
||||
/// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -117,17 +132,16 @@ impl File {
|
|||
/// ```
|
||||
pub async fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
|
||||
let path = path.as_ref().to_owned();
|
||||
let file = blocking::spawn(async move { fs::File::create(&path) }).await?;
|
||||
let file = blocking::spawn(async move { std::fs::File::create(&path) }).await?;
|
||||
Ok(file.into())
|
||||
}
|
||||
|
||||
/// Attempts to synchronize all OS-internal metadata to disk.
|
||||
/// Synchronizes OS-internal buffered contents and metadata to disk.
|
||||
///
|
||||
/// This function will attempt to ensure that all in-memory data reaches the filesystem before
|
||||
/// returning.
|
||||
/// This function will ensure that all in-memory data reaches the filesystem.
|
||||
///
|
||||
/// This can be used to handle errors that would otherwise only be caught when the `File` is
|
||||
/// closed. Dropping a file will ignore errors in synchronizing this in-memory data.
|
||||
/// This can be used to handle errors that would otherwise only be caught when the file is
|
||||
/// closed. When a file is dropped, errors in synchronizing this in-memory data are ignored.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -154,14 +168,16 @@ impl File {
|
|||
blocking::spawn(async move { state.file.sync_all() }).await
|
||||
}
|
||||
|
||||
/// Similar to [`sync_all`], except that it may not synchronize file metadata.
|
||||
/// Synchronizes OS-internal buffered contents to disk.
|
||||
///
|
||||
/// 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.
|
||||
/// This is similar to [`sync_all`], except that file metadata may not be synchronized.
|
||||
///
|
||||
/// This is intended for use cases that must synchronize the contents of the file, but don't
|
||||
/// need the file metadata synchronized to disk.
|
||||
///
|
||||
/// Note that some platforms may simply implement this in terms of [`sync_all`].
|
||||
///
|
||||
/// [`sync_all`]: struct.File.html#method.sync_all
|
||||
/// [`sync_all`]: #method.sync_all
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -188,18 +204,14 @@ impl File {
|
|||
blocking::spawn(async move { state.file.sync_data() }).await
|
||||
}
|
||||
|
||||
/// Truncates or extends the underlying file.
|
||||
/// Truncates or extends the file.
|
||||
///
|
||||
/// If the `size` is less than the current file's size, then the file will be truncated. 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 zeros.
|
||||
/// If `size` is less than the current file size, then the file will be truncated. If it is
|
||||
/// greater than the current file size, then the file will be extended to `size` and have all
|
||||
/// intermediate data filled with zeros.
|
||||
///
|
||||
/// The file's cursor isn't changed. In particular, if the cursor was at the end and the file
|
||||
/// is truncated using this operation, the cursor will now be past the end.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if the file is not opened for writing.
|
||||
/// The file's cursor stays at the same position, even if the cursor ends up being past the end
|
||||
/// of the file after this operation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -225,7 +237,7 @@ impl File {
|
|||
blocking::spawn(async move { state.file.set_len(size) }).await
|
||||
}
|
||||
|
||||
/// Queries metadata about the file.
|
||||
/// Reads the file's metadata.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -239,17 +251,19 @@ impl File {
|
|||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn metadata(&self) -> io::Result<fs::Metadata> {
|
||||
pub async fn metadata(&self) -> io::Result<Metadata> {
|
||||
let file = self.file.clone();
|
||||
blocking::spawn(async move { file.metadata() }).await
|
||||
}
|
||||
|
||||
/// Changes the permissions on the underlying file.
|
||||
/// Changes the permissions on the file.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if the user lacks permission to change attributes on the
|
||||
/// underlying file, but may also return an error in other OS-specific cases.
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * The current process lacks permissions to change attributes on the file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -266,7 +280,7 @@ impl File {
|
|||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn set_permissions(&self, perm: fs::Permissions) -> io::Result<()> {
|
||||
pub async fn set_permissions(&self, perm: Permissions) -> io::Result<()> {
|
||||
let file = self.file.clone();
|
||||
blocking::spawn(async move { file.set_permissions(perm) }).await
|
||||
}
|
||||
|
@ -282,6 +296,12 @@ impl Drop for File {
|
|||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.file.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for File {
|
||||
fn poll_read(
|
||||
self: Pin<&mut Self>,
|
||||
|
@ -374,9 +394,9 @@ impl AsyncSeek for &File {
|
|||
}
|
||||
|
||||
impl From<std::fs::File> for File {
|
||||
/// Converts a `std::fs::File` into its asynchronous equivalent.
|
||||
fn from(file: fs::File) -> File {
|
||||
fn from(file: std::fs::File) -> File {
|
||||
let file = Arc::new(file);
|
||||
|
||||
File {
|
||||
file: file.clone(),
|
||||
lock: Lock::new(State {
|
||||
|
@ -413,7 +433,7 @@ cfg_if! {
|
|||
|
||||
impl FromRawFd for File {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> File {
|
||||
fs::File::from_raw_fd(fd).into()
|
||||
std::fs::File::from_raw_fd(fd).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,7 +442,7 @@ cfg_if! {
|
|||
let file = self.file.clone();
|
||||
drop(self);
|
||||
Arc::try_unwrap(file)
|
||||
.expect("cannot acquire ownership of file handle after drop")
|
||||
.expect("cannot acquire ownership of the file handle after drop")
|
||||
.into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
@ -440,7 +460,7 @@ cfg_if! {
|
|||
|
||||
impl FromRawHandle for File {
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> File {
|
||||
fs::File::from_raw_handle(handle).into()
|
||||
std::fs::File::from_raw_handle(handle).into()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -449,7 +469,7 @@ cfg_if! {
|
|||
let file = self.file.clone();
|
||||
drop(self);
|
||||
Arc::try_unwrap(file)
|
||||
.expect("cannot acquire ownership of file handle after drop")
|
||||
.expect("cannot acquire ownership of the file handle after drop")
|
||||
.into_raw_handle()
|
||||
}
|
||||
}
|
||||
|
@ -457,13 +477,11 @@ cfg_if! {
|
|||
}
|
||||
|
||||
/// An async mutex with non-borrowing lock guards.
|
||||
#[derive(Debug)]
|
||||
struct Lock<T>(Arc<LockState<T>>);
|
||||
|
||||
unsafe impl<T: Send> Send for Lock<T> {}
|
||||
unsafe impl<T: Send> Sync for Lock<T> {}
|
||||
|
||||
#[derive(Debug)]
|
||||
/// The state of a lock.
|
||||
struct LockState<T> {
|
||||
/// Set to `true` when locked.
|
||||
|
@ -472,12 +490,12 @@ struct LockState<T> {
|
|||
/// The inner value.
|
||||
value: UnsafeCell<T>,
|
||||
|
||||
/// A list of tasks interested in locking.
|
||||
/// A list of tasks interested in acquiring the lock.
|
||||
wakers: Mutex<Vec<Waker>>,
|
||||
}
|
||||
|
||||
impl<T> Lock<T> {
|
||||
/// Creates a new lock with the given value.
|
||||
/// Creates a new lock initialized with `value`.
|
||||
fn new(value: T) -> Lock<T> {
|
||||
Lock(Arc::new(LockState {
|
||||
locked: AtomicBool::new(false),
|
||||
|
@ -511,14 +529,13 @@ impl<T> Lock<T> {
|
|||
/// A lock guard.
|
||||
///
|
||||
/// When dropped, ownership of the inner value is returned back to the lock.
|
||||
#[derive(Debug)]
|
||||
struct LockGuard<T>(Arc<LockState<T>>);
|
||||
|
||||
unsafe impl<T: Send> Send for LockGuard<T> {}
|
||||
unsafe impl<T: Sync> Sync for LockGuard<T> {}
|
||||
|
||||
impl<T> LockGuard<T> {
|
||||
/// Registers a task interested in locking.
|
||||
/// Registers a task interested in acquiring the lock.
|
||||
///
|
||||
/// When this lock guard gets dropped, all registered tasks will be woken up.
|
||||
fn register(&self, cx: &Context<'_>) {
|
||||
|
@ -532,8 +549,10 @@ impl<T> LockGuard<T> {
|
|||
|
||||
impl<T> Drop for LockGuard<T> {
|
||||
fn drop(&mut self) {
|
||||
// Release the lock.
|
||||
self.0.locked.store(false, Ordering::Release);
|
||||
|
||||
// Wake up all registered tasks interested in acquiring the lock.
|
||||
for w in self.0.wakers.lock().unwrap().drain(..) {
|
||||
w.wake();
|
||||
}
|
||||
|
@ -557,14 +576,13 @@ impl<T> DerefMut for LockGuard<T> {
|
|||
/// Modes a file can be in.
|
||||
///
|
||||
/// The file can either be in idle mode, reading mode, or writing mode.
|
||||
#[derive(Debug)]
|
||||
enum Mode {
|
||||
/// The cache is empty.
|
||||
Idle,
|
||||
|
||||
/// The cache contains data read from the inner file.
|
||||
///
|
||||
/// This `usize` represents how many bytes from the beginning of cache have been consumed.
|
||||
/// The `usize` represents how many bytes from the beginning of cache have been consumed.
|
||||
Reading(usize),
|
||||
|
||||
/// The cache contains data that needs to be written to the inner file.
|
||||
|
@ -573,14 +591,13 @@ enum Mode {
|
|||
|
||||
/// The current state of a file.
|
||||
///
|
||||
/// The `File` struct puts this state behind a lock.
|
||||
/// The `File` struct protects this state behind a lock.
|
||||
///
|
||||
/// Filesystem operations that get spawned as blocking tasks will take ownership of the state and
|
||||
/// return it back once the operation completes.
|
||||
#[derive(Debug)]
|
||||
/// Filesystem operations that get spawned as blocking tasks will acquire the lock, take ownership
|
||||
/// of the state and return it back once the operation completes.
|
||||
struct State {
|
||||
/// The inner file.
|
||||
file: Arc<fs::File>,
|
||||
file: Arc<std::fs::File>,
|
||||
|
||||
/// The current mode (idle, reading, or writing).
|
||||
mode: Mode,
|
||||
|
@ -588,10 +605,10 @@ struct State {
|
|||
/// The read/write cache.
|
||||
///
|
||||
/// If in reading mode, the cache contains a chunk of data that has been read from the file.
|
||||
/// If in writing mode, the cache contains data that will eventually be written into the file.
|
||||
/// If in writing mode, the cache contains data that will eventually be written to the file.
|
||||
cache: Vec<u8>,
|
||||
|
||||
/// `true` if the file is flushed.
|
||||
/// Set to `true` if the file is flushed.
|
||||
///
|
||||
/// When a file is flushed, the write cache and the inner file's buffer are empty.
|
||||
is_flushed: bool,
|
||||
|
@ -607,17 +624,45 @@ impl LockGuard<State> {
|
|||
/// Seeks to a new position in the file.
|
||||
fn poll_seek(mut self, cx: &mut Context<'_>, pos: SeekFrom) -> Poll<io::Result<u64>> {
|
||||
// If this operation doesn't move the cursor, then poll the current position inside the
|
||||
// file. This call will hopefully not block.
|
||||
// file. This call should not block because it doesn't touch the actual file on disk.
|
||||
if pos == SeekFrom::Current(0) {
|
||||
return Poll::Ready((&*self.file).seek(pos));
|
||||
// Poll the internal file cursor.
|
||||
let internal = (&*self.file).seek(SeekFrom::Current(0))?;
|
||||
|
||||
// Factor in the difference caused by caching.
|
||||
let actual = match self.mode {
|
||||
Mode::Idle => internal,
|
||||
Mode::Reading(start) => internal - self.cache.len() as u64 + start as u64,
|
||||
Mode::Writing => internal + self.cache.len() as u64,
|
||||
};
|
||||
return Poll::Ready(Ok(actual));
|
||||
}
|
||||
|
||||
// If the file is in reading mode and the cache will stay valid after seeking, then adjust
|
||||
// the current position in the read cache without invaliding it.
|
||||
if let Mode::Reading(start) = self.mode {
|
||||
if let SeekFrom::Current(diff) = pos {
|
||||
if let Some(new) = (start as i64).checked_add(diff) {
|
||||
if 0 <= new && new <= self.cache.len() as i64 {
|
||||
// Poll the internal file cursor.
|
||||
let internal = (&*self.file).seek(SeekFrom::Current(0))?;
|
||||
|
||||
// Adjust the current position in the read cache.
|
||||
self.mode = Mode::Reading(new as usize);
|
||||
|
||||
// Factor in the difference caused by caching.
|
||||
return Poll::Ready(Ok(internal - self.cache.len() as u64 + new as u64));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate the read cache and flush the write cache before calling `seek()`.
|
||||
self = futures_core::ready!(self.poll_unread(cx))?;
|
||||
self = futures_core::ready!(self.poll_flush(cx))?;
|
||||
|
||||
// Seek to the new position. This call is hopefully not blocking because it should just
|
||||
// change the internal offset into the file and not touch the actual file.
|
||||
// Seek to the new position. This call should not block because it only changes the
|
||||
// internal offset into the file and doesn't touch the actual file on disk.
|
||||
Poll::Ready((&*self.file).seek(pos))
|
||||
}
|
||||
|
||||
|
@ -702,13 +747,12 @@ impl LockGuard<State> {
|
|||
match self.mode {
|
||||
Mode::Idle | Mode::Writing => Poll::Ready(Ok(self)),
|
||||
Mode::Reading(start) => {
|
||||
// Number of unconsumed bytes in the read cache.
|
||||
// The number of unconsumed bytes in the read cache.
|
||||
let n = self.cache.len() - start;
|
||||
|
||||
if n > 0 {
|
||||
// Seek `n` bytes backwards. This call is hopefully not blocking because it
|
||||
// should just change the internal offset into the file and not touch the
|
||||
// actual file.
|
||||
// Seek `n` bytes backwards. This call should not block because it only changes
|
||||
// the internal offset into the file and doesn't touch the actual file on disk.
|
||||
(&*self.file).seek(SeekFrom::Current(-(n as i64)))?;
|
||||
}
|
||||
|
||||
|
@ -731,7 +775,7 @@ impl LockGuard<State> {
|
|||
// If we're in reading mode, invalidate the read buffer.
|
||||
self = futures_core::ready!(self.poll_unread(cx))?;
|
||||
|
||||
// Make the cache have as much capacity as `buf`.
|
||||
// If necessary, grow the cache to have as much capacity as `buf`.
|
||||
if self.cache.capacity() < buf.len() {
|
||||
let diff = buf.len() - self.cache.capacity();
|
||||
self.cache.reserve(diff);
|
||||
|
@ -740,7 +784,7 @@ impl LockGuard<State> {
|
|||
// How many bytes can be written into the cache before filling up.
|
||||
let available = self.cache.capacity() - self.cache.len();
|
||||
|
||||
// If there is available space in the cache or if the buffer is empty, we can write data
|
||||
// If there is space available in the cache or if the buffer is empty, we can write data
|
||||
// into the cache.
|
||||
if available > 0 || buf.is_empty() {
|
||||
let n = cmp::min(available, buf.len());
|
||||
|
|
86
src/fs/file_type.rs
Normal file
86
src/fs/file_type.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "docs")] {
|
||||
/// The type of a file or directory.
|
||||
///
|
||||
/// A file type is returned by [`Metadata::file_type`].
|
||||
///
|
||||
/// Note that file types are mutually exclusive, i.e. at most one of methods [`is_dir`],
|
||||
/// [`is_file`], and [`is_symlink`] can return `true`.
|
||||
///
|
||||
/// This type is a re-export of [`std::fs::FileType`].
|
||||
///
|
||||
/// [`Metadata::file_type`]: struct.Metadata.html#method.file_type
|
||||
/// [`is_dir`]: #method.is_dir
|
||||
/// [`is_file`]: #method.is_file
|
||||
/// [`is_symlink`]: #method.is_symlink
|
||||
/// [`std::fs::FileType`]: https://doc.rust-lang.org/std/fs/struct.FileType.html
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
pub struct FileType {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
/// Returns `true` if this file type represents a regular directory.
|
||||
///
|
||||
/// If this file type represents a symbolic link, this method returns `false`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// let file_type = fs::metadata(".").await?.file_type();
|
||||
/// println!("{:?}", file_type.is_dir());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn is_dir(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns `true` if this file type represents a regular file.
|
||||
///
|
||||
/// If this file type represents a symbolic link, this method returns `false`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// let file_type = fs::metadata("a.txt").await?.file_type();
|
||||
/// println!("{:?}", file_type.is_file());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn is_file(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns `true` if this file type represents a symbolic link.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// let file_type = fs::metadata("a.txt").await?.file_type();
|
||||
/// println!("{:?}", file_type.is_symlink());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pub use std::fs::FileType;
|
||||
}
|
||||
}
|
|
@ -1,13 +1,12 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Creates a new hard link on the filesystem.
|
||||
/// Creates a 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.
|
||||
/// The `dst` path will be a link pointing to the `src` path. Note that operating systems often
|
||||
/// require these two paths to be located on the same filesystem.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::hard_link`].
|
||||
///
|
||||
|
@ -15,9 +14,10 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * The `src` path is not a file or doesn't exist.
|
||||
/// * `src` does not point to an existing file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -33,5 +33,5 @@ use crate::task::blocking;
|
|||
pub async fn hard_link<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
|
||||
let from = from.as_ref().to_owned();
|
||||
let to = to.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::hard_link(&from, &to) }).await
|
||||
blocking::spawn(async move { std::fs::hard_link(&from, &to) }).await
|
||||
}
|
||||
|
|
|
@ -1,23 +1,28 @@
|
|||
use std::fs::{self, Metadata};
|
||||
use std::path::Path;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Queries the metadata for a path.
|
||||
/// Reads metadata for a path.
|
||||
///
|
||||
/// This function will traverse symbolic links to query information about the file or directory.
|
||||
/// This function will traverse symbolic links to read metadata for the target file or directory.
|
||||
/// If you want to read metadata without following symbolic links, use [`symlink_metadata`]
|
||||
/// instead.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::metadata`].
|
||||
///
|
||||
/// [`symlink_metadata`]: fn.symlink_metadata.html
|
||||
/// [`std::fs::metadata`]: https://doc.rust-lang.org/std/fs/fn.metadata.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` does not exist.
|
||||
/// * The current process lacks permissions to query metadata for `path`.
|
||||
/// * `path` does not point to an existing file or directory.
|
||||
/// * The current process lacks permissions to read metadata for the path.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -32,5 +37,196 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::metadata(path) }).await
|
||||
blocking::spawn(async move { std::fs::metadata(path) }).await
|
||||
}
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "docs")] {
|
||||
use std::time::SystemTime;
|
||||
|
||||
use crate::fs::{FileType, Permissions};
|
||||
|
||||
/// Metadata for a file or directory.
|
||||
///
|
||||
/// Metadata is returned by [`metadata`] and [`symlink_metadata`].
|
||||
///
|
||||
/// This type is a re-export of [`std::fs::Metadata`].
|
||||
///
|
||||
/// [`metadata`]: fn.metadata.html
|
||||
/// [`symlink_metadata`]: fn.symlink_metadata.html
|
||||
/// [`is_dir`]: #method.is_dir
|
||||
/// [`is_file`]: #method.is_file
|
||||
/// [`std::fs::Metadata`]: https://doc.rust-lang.org/std/fs/struct.Metadata.html
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Metadata {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl Metadata {
|
||||
/// Returns the file type from this metadata.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{:?}", metadata.file_type());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn file_type(&self) -> FileType {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns `true` if this metadata is for a regular directory.
|
||||
///
|
||||
/// If this metadata is for a symbolic link, this method returns `false`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata(".").await?;
|
||||
/// println!("{:?}", metadata.is_dir());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn is_dir(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns `true` if this metadata is for a regular file.
|
||||
///
|
||||
/// If this metadata is for a symbolic link, this method returns `false`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{:?}", metadata.is_file());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn is_file(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the file size in bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{}", metadata.len());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn len(&self) -> u64 {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the permissions from this metadata.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{:?}", metadata.permissions());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn permissions(&self) -> Permissions {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the last modification time.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This data may not be available on all platforms, in which case an error will be
|
||||
/// returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{:?}", metadata.modified());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the last access time.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This data may not be available on all platforms, in which case an error will be
|
||||
/// returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{:?}", metadata.accessed());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Returns the creation time.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This data may not be available on all platforms, in which case an error will be
|
||||
/// returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use std::fs;
|
||||
///
|
||||
/// let metadata = fs::metadata("a.txt").await?;
|
||||
/// println!("{:?}", metadata.created());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pub use std::fs::Metadata;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,13 @@
|
|||
//!
|
||||
//! This module is an async version of [`std::fs`].
|
||||
//!
|
||||
//! [`os::unix::fs`]: ../os/unix/fs/index.html
|
||||
//! [`std::fs`]: https://doc.rust-lang.org/std/fs/index.html
|
||||
//!
|
||||
//! # Platform-specific extensions
|
||||
//!
|
||||
//! * Unix: use the [`os::unix::fs`] module.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Create a new file and write some bytes to it:
|
||||
|
@ -23,12 +28,12 @@
|
|||
pub use dir_builder::DirBuilder;
|
||||
pub use dir_entry::DirEntry;
|
||||
pub use file::File;
|
||||
pub use file_type::FileType;
|
||||
pub use metadata::Metadata;
|
||||
pub use open_options::OpenOptions;
|
||||
pub use permissions::Permissions;
|
||||
pub use read_dir::ReadDir;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use std::fs::{FileType, Metadata, Permissions};
|
||||
|
||||
pub use canonicalize::canonicalize;
|
||||
pub use copy::copy;
|
||||
pub use create_dir::create_dir;
|
||||
|
@ -54,9 +59,11 @@ mod create_dir_all;
|
|||
mod dir_builder;
|
||||
mod dir_entry;
|
||||
mod file;
|
||||
mod file_type;
|
||||
mod hard_link;
|
||||
mod metadata;
|
||||
mod open_options;
|
||||
mod permissions;
|
||||
mod read;
|
||||
mod read_dir;
|
||||
mod read_link;
|
||||
|
|
|
@ -1,35 +1,35 @@
|
|||
use std::fs;
|
||||
use std::io;
|
||||
use std::path::Path;
|
||||
|
||||
use cfg_if::cfg_if;
|
||||
|
||||
use super::File;
|
||||
use crate::fs::File;
|
||||
use crate::future::Future;
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Options and flags which for configuring how a file is opened.
|
||||
/// A builder for opening files with configurable options.
|
||||
///
|
||||
/// This builder exposes the ability to configure how a [`File`] is opened and what operations are
|
||||
/// permitted on the open file. The [`File::open`] and [`File::create`] methods are aliases for
|
||||
/// commonly used options with this builder.
|
||||
/// Files can be opened in [`read`] and/or [`write`] mode.
|
||||
///
|
||||
/// Generally speaking, when using `OpenOptions`, you'll first call [`new`], then chain calls to
|
||||
/// methods to set each option, then call [`open`], passing the path of the file you're trying to
|
||||
/// open. This will give you a [`File`] inside that you can further operate on.
|
||||
/// The [`append`] option opens files in a special writing mode that moves the file cursor to the
|
||||
/// end of file before every write operation.
|
||||
///
|
||||
/// It is also possible to [`truncate`] the file right after opening, to [`create`] a file if it
|
||||
/// doesn't exist yet, or to always create a new file with [`create_new`].
|
||||
///
|
||||
/// This type is an async version of [`std::fs::OpenOptions`].
|
||||
///
|
||||
/// [`new`]: struct.OpenOptions.html#method.new
|
||||
/// [`open`]: struct.OpenOptions.html#method.open
|
||||
/// [`File`]: struct.File.html
|
||||
/// [`File::open`]: struct.File.html#method.open
|
||||
/// [`File::create`]: struct.File.html#method.create
|
||||
/// [`read`]: #method.read
|
||||
/// [`write`]: #method.write
|
||||
/// [`append`]: #method.append
|
||||
/// [`truncate`]: #method.truncate
|
||||
/// [`create`]: #method.create
|
||||
/// [`create_new`]: #method.create_new
|
||||
/// [`std::fs::OpenOptions`]: https://doc.rust-lang.org/std/fs/struct.OpenOptions.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Opening a file for reading:
|
||||
/// Open a file for reading:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
|
@ -44,7 +44,7 @@ use crate::task::blocking;
|
|||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
///
|
||||
/// Opening a file for both reading and writing, creating it if it doesn't exist:
|
||||
/// Open a file for both reading and writing, and create it if it doesn't exist yet:
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
|
@ -61,10 +61,10 @@ use crate::task::blocking;
|
|||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions(fs::OpenOptions);
|
||||
pub struct OpenOptions(std::fs::OpenOptions);
|
||||
|
||||
impl OpenOptions {
|
||||
/// Creates a blank new set of options.
|
||||
/// Creates a blank set of options.
|
||||
///
|
||||
/// All options are initially set to `false`.
|
||||
///
|
||||
|
@ -83,12 +83,12 @@ impl OpenOptions {
|
|||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn new() -> OpenOptions {
|
||||
OpenOptions(fs::OpenOptions::new())
|
||||
OpenOptions(std::fs::OpenOptions::new())
|
||||
}
|
||||
|
||||
/// Sets the option for read access.
|
||||
/// Configures the option for read mode.
|
||||
///
|
||||
/// This option, when `true`, will indicate that the file should be readable if opened.
|
||||
/// When set to `true`, this option means the file will be readable after opening.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -109,11 +109,11 @@ impl OpenOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the option for write access.
|
||||
/// Configures the option for write mode.
|
||||
///
|
||||
/// This option, when `true`, will indicate that the file should be writable if opened.
|
||||
/// When set to `true`, this option means the file will be writable after opening.
|
||||
///
|
||||
/// If the file already exists, any write calls on it will overwrite its contents, without
|
||||
/// If the file already exists, write calls on it will overwrite the previous contents without
|
||||
/// truncating it.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -135,31 +135,10 @@ impl OpenOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the option for append mode.
|
||||
/// Configures the option for append mode.
|
||||
///
|
||||
/// This option, when `true`, means that writes will append to a file instead of overwriting
|
||||
/// previous contents. Note that setting `.write(true).append(true)` has the same effect as
|
||||
/// setting only `.append(true)`.
|
||||
///
|
||||
/// For most filesystems, the operating system guarantees that all writes are atomic: no writes
|
||||
/// get mangled because another process writes at the same time.
|
||||
///
|
||||
/// One maybe obvious note when using append mode: make sure that all data that belongs
|
||||
/// together is written to the file in one operation. This can be done by concatenating strings
|
||||
/// before writing them, or using a buffered writer (with a buffer of adequate size), and
|
||||
/// flushing when the message is complete.
|
||||
///
|
||||
/// If a file is opened with both read and append access, beware that after opening and after
|
||||
/// every write, the position for reading may be set at the end of the file. So, before
|
||||
/// writing, save the current position by seeking with a zero offset, and restore it before the
|
||||
/// next read.
|
||||
///
|
||||
/// ## Note
|
||||
///
|
||||
/// This function doesn't create the file if it doesn't exist. Use the [`create`] method to do
|
||||
/// so.
|
||||
///
|
||||
/// [`create`]: #method.create
|
||||
/// When set to `true`, this option means the file will be writable after opening and the file
|
||||
/// cursor will be moved to the end of file before every write operaiton.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -180,12 +159,14 @@ impl OpenOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the option for truncating a previous file.
|
||||
/// Configures the option for truncating the previous file.
|
||||
///
|
||||
/// If a file is successfully opened with this option set, it will truncate the file to 0
|
||||
/// length if it already exists.
|
||||
/// When set to `true`, the file will be truncated to the length of 0 bytes.
|
||||
///
|
||||
/// The file must be opened with write access for truncation to work.
|
||||
/// The file must be opened in [`write`] or [`append`] mode for truncation to work.
|
||||
///
|
||||
/// [`write`]: #method.write
|
||||
/// [`append`]: #method.append
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -207,11 +188,11 @@ impl OpenOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the option for creating a new file.
|
||||
/// Configures the option for creating a new file if it doesn't exist.
|
||||
///
|
||||
/// This option indicates whether a new file will be created if the file does not yet exist.
|
||||
/// When set to `true`, this option means a new file will be created if it doesn't exist.
|
||||
///
|
||||
/// In order for the file to be created, [`write`] or [`append`] access must be used.
|
||||
/// The file must be opened in [`write`] or [`append`] mode for file creation to work.
|
||||
///
|
||||
/// [`write`]: #method.write
|
||||
/// [`append`]: #method.append
|
||||
|
@ -236,21 +217,15 @@ impl OpenOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Sets the option to always create a new file.
|
||||
/// Configures the option for creating a new file or failing if it already exists.
|
||||
///
|
||||
/// This option indicates whether a new file will be created. No file is allowed to exist at
|
||||
/// the target location, also no (dangling) symlink.
|
||||
/// When set to `true`, this option means a new file will be created, or the open operation
|
||||
/// will fail if the file already exists.
|
||||
///
|
||||
/// This option is useful because it is atomic. Otherwise, between checking whether a file
|
||||
/// exists and creating a new one, the file may have been created by another process (a TOCTOU
|
||||
/// race condition / attack).
|
||||
/// The file must be opened in [`write`] or [`append`] mode for file creation to work.
|
||||
///
|
||||
/// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are ignored.
|
||||
///
|
||||
/// The file must be opened with write or append access in order to create a new file.
|
||||
///
|
||||
/// [`.create()`]: #method.create
|
||||
/// [`.truncate()`]: #method.truncate
|
||||
/// [`write`]: #method.write
|
||||
/// [`append`]: #method.append
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -272,37 +247,27 @@ impl OpenOptions {
|
|||
self
|
||||
}
|
||||
|
||||
/// Opens a file at specified path with the configured options.
|
||||
/// Opens a file with the configured options.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error under a number of different circumstances. Some of these
|
||||
/// error conditions are listed here, together with their [`ErrorKind`]. The mapping to
|
||||
/// [`ErrorKind`]s is not part of the compatibility contract of the function, especially the
|
||||
/// `Other` kind might change to more specific kinds in the future.
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * [`NotFound`]: The specified file does not exist and neither `create` or `create_new` is
|
||||
/// set.
|
||||
/// * [`NotFound`]: One of the directory components of the file path does not exist.
|
||||
/// * [`PermissionDenied`]: The user lacks permission to get the specified access rights for
|
||||
/// the file.
|
||||
/// * [`PermissionDenied`]: The user lacks permission to open one of the directory components
|
||||
/// of the specified path.
|
||||
/// * [`AlreadyExists`]: `create_new` was specified and the file already exists.
|
||||
/// * [`InvalidInput`]: Invalid combinations of open options (truncate without write access, no
|
||||
/// access mode set, etc.).
|
||||
/// * [`Other`]: One of the directory components of the specified file path was not, in fact, a
|
||||
/// directory.
|
||||
/// * [`Other`]: Filesystem-level errors: full disk, write permission requested on a read-only
|
||||
/// file system, exceeded disk quota, too many open files, too long filename, too many
|
||||
/// symbolic links in the specified path (Unix-like systems only), etc.
|
||||
/// * The file does not exist and neither [`create`] nor [`create_new`] were set.
|
||||
/// * The file's parent directory does not exist.
|
||||
/// * The current process lacks permissions to open the file in the configured mode.
|
||||
/// * The file already exists and [`create_new`] was set.
|
||||
/// * Invalid combination of options was used, like [`truncate`] was set but [`write`] wasn't,
|
||||
/// or none of [`read`], [`write`], and [`append`] modes was set.
|
||||
/// * An OS-level occurred, like too many files are open or the file name is too long.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// [`ErrorKind`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html
|
||||
/// [`AlreadyExists`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.AlreadyExists
|
||||
/// [`InvalidInput`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.InvalidInput
|
||||
/// [`NotFound`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.NotFound
|
||||
/// [`Other`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.Other
|
||||
/// [`PermissionDenied`]: https://doc.rust-lang.org/std/io/enum.ErrorKind.html#variant.PermissionDenied
|
||||
/// [`read`]: #method.read
|
||||
/// [`write`]: #method.write
|
||||
/// [`append`]: #method.append
|
||||
/// [`truncate`]: #method.truncate
|
||||
/// [`create`]: #method.create
|
||||
/// [`create_new`]: #method.create_new
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -311,7 +276,10 @@ impl OpenOptions {
|
|||
/// #
|
||||
/// use async_std::fs::OpenOptions;
|
||||
///
|
||||
/// let file = OpenOptions::new().open("a.txt").await?;
|
||||
/// let file = OpenOptions::new()
|
||||
/// .read(true)
|
||||
/// .open("a.txt")
|
||||
/// .await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
|
58
src/fs/permissions.rs
Normal file
58
src/fs/permissions.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use cfg_if::cfg_if;
|
||||
|
||||
cfg_if! {
|
||||
if #[cfg(feature = "docs")] {
|
||||
/// A set of permissions on a file or directory.
|
||||
///
|
||||
/// This type is a re-export of [`std::fs::Permissions`].
|
||||
///
|
||||
/// [`std::fs::Permissions`]: https://doc.rust-lang.org/std/fs/struct.Permissions.html
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct Permissions {
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl Permissions {
|
||||
/// Returns the read-only flag.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// let perm = fs::metadata("a.txt").await?.permissions();
|
||||
/// println!("{:?}", perm.readonly());
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn readonly(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
/// Configures the read-only flag.
|
||||
///
|
||||
/// [`fs::set_permissions`]: fn.set_permissions.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
|
||||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// let mut perm = fs::metadata("a.txt").await?.permissions();
|
||||
/// perm.set_readonly(true);
|
||||
/// fs::set_permissions("a.txt", perm).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn set_readonly(&mut self, readonly: bool) {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pub use std::fs::Permissions;
|
||||
}
|
||||
}
|
|
@ -1,25 +1,28 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Read the entire contents of a file into a bytes vector.
|
||||
/// Reads the entire contents of a file as raw bytes.
|
||||
///
|
||||
/// This is a convenience function for reading entire files. It pre-allocates a buffer based on the
|
||||
/// file size when available, so it is generally faster than manually opening a file and reading
|
||||
/// into a `Vec`.
|
||||
/// file size when available, so it is typically faster than manually opening a file and reading
|
||||
/// from it.
|
||||
///
|
||||
/// If you want to read the contents as a string, use [`read_to_string`] instead.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::read`].
|
||||
///
|
||||
/// [`read_to_string`]: fn.read_to_string.html
|
||||
/// [`std::fs::read`]: https://doc.rust-lang.org/std/fs/fn.read.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` does not exist.
|
||||
/// * The current process lacks permissions to read `path`.
|
||||
/// * `path` does not point to an existing file.
|
||||
/// * The current process lacks permissions to read the file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -34,5 +37,5 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn read<P: AsRef<Path>>(path: P) -> io::Result<Vec<u8>> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::read(path) }).await
|
||||
blocking::spawn(async move { std::fs::read(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,30 +1,29 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::pin::Pin;
|
||||
|
||||
use super::DirEntry;
|
||||
use crate::fs::DirEntry;
|
||||
use crate::future::Future;
|
||||
use crate::io;
|
||||
use crate::task::{blocking, Context, Poll};
|
||||
|
||||
/// Returns a stream over the entries within a directory.
|
||||
/// Returns a stream of entries in a directory.
|
||||
///
|
||||
/// The stream yields items of type [`io::Result`]`<`[`DirEntry`]`>`. New errors may be encountered
|
||||
/// after a stream is initially constructed.
|
||||
/// The stream yields items of type [`io::Result`]`<`[`DirEntry`]`>`. Note that I/O errors can
|
||||
/// occur while reading from the stream.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::read_dir`].
|
||||
///
|
||||
/// [`io::Result`]: https://doc.rust-lang.org/std/io/type.Result.html
|
||||
/// [`io::Result`]: ../io/type.Result.html
|
||||
/// [`DirEntry`]: struct.DirEntry.html
|
||||
/// [`std::fs::read_dir`]: https://doc.rust-lang.org/std/fs/fn.read_dir.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` does not exist.
|
||||
/// * `path` does not point at a directory.
|
||||
/// * The current process lacks permissions to view the contents of `path`.
|
||||
/// * `path` does not point to an existing directory.
|
||||
/// * The current process lacks permissions to read the contents of the directory.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -34,23 +33,23 @@ use crate::task::{blocking, Context, Poll};
|
|||
/// use async_std::fs;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut dir = fs::read_dir(".").await?;
|
||||
/// let mut entries = fs::read_dir(".").await?;
|
||||
///
|
||||
/// while let Some(entry) = dir.next().await {
|
||||
/// let entry = entry?;
|
||||
/// println!("{:?}", entry.file_name());
|
||||
/// while let Some(res) = entries.next().await {
|
||||
/// let entry = res?;
|
||||
/// println!("{}", entry.file_name().to_string_lossy());
|
||||
/// }
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::read_dir(path) })
|
||||
blocking::spawn(async move { std::fs::read_dir(path) })
|
||||
.await
|
||||
.map(ReadDir::new)
|
||||
}
|
||||
|
||||
/// A stream over entries in a directory.
|
||||
/// A stream of entries in a directory.
|
||||
///
|
||||
/// This stream is returned by [`read_dir`] and yields items of type
|
||||
/// [`io::Result`]`<`[`DirEntry`]`>`. Each [`DirEntry`] can then retrieve information like entry's
|
||||
|
@ -59,7 +58,7 @@ pub async fn read_dir<P: AsRef<Path>>(path: P) -> io::Result<ReadDir> {
|
|||
/// This type is an async version of [`std::fs::ReadDir`].
|
||||
///
|
||||
/// [`read_dir`]: fn.read_dir.html
|
||||
/// [`io::Result`]: https://doc.rust-lang.org/std/io/type.Result.html
|
||||
/// [`io::Result`]: ../io/type.Result.html
|
||||
/// [`DirEntry`]: struct.DirEntry.html
|
||||
/// [`std::fs::ReadDir`]: https://doc.rust-lang.org/std/fs/struct.ReadDir.html
|
||||
#[derive(Debug)]
|
||||
|
@ -70,13 +69,13 @@ pub struct ReadDir(State);
|
|||
/// The `ReadDir` can be either idle or busy performing an asynchronous operation.
|
||||
#[derive(Debug)]
|
||||
enum State {
|
||||
Idle(Option<fs::ReadDir>),
|
||||
Busy(blocking::JoinHandle<(fs::ReadDir, Option<io::Result<fs::DirEntry>>)>),
|
||||
Idle(Option<std::fs::ReadDir>),
|
||||
Busy(blocking::JoinHandle<(std::fs::ReadDir, Option<io::Result<std::fs::DirEntry>>)>),
|
||||
}
|
||||
|
||||
impl ReadDir {
|
||||
/// Creates an asynchronous `ReadDir` from a synchronous handle.
|
||||
pub(crate) fn new(inner: fs::ReadDir) -> ReadDir {
|
||||
pub(crate) fn new(inner: std::fs::ReadDir) -> ReadDir {
|
||||
ReadDir(State::Idle(Some(inner)))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Reads a symbolic link, returning the path it points to.
|
||||
/// Reads a symbolic link and returns the path it points to.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::read_link`].
|
||||
///
|
||||
|
@ -12,10 +11,10 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` is not a symbolic link.
|
||||
/// * `path` does not exist.
|
||||
/// * `path` does not point to an existing link.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -30,5 +29,5 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::read_link(path) }).await
|
||||
blocking::spawn(async move { std::fs::read_link(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,21 +1,29 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Read the entire contents of a file into a string.
|
||||
/// Reads the entire contents of a file as a string.
|
||||
///
|
||||
/// This is a convenience function for reading entire files. It pre-allocates a string based on the
|
||||
/// file size when available, so it is typically faster than manually opening a file and reading
|
||||
/// from it.
|
||||
///
|
||||
/// If you want to read the contents as raw bytes, use [`read`] instead.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::read_to_string`].
|
||||
///
|
||||
/// [`read`]: fn.read.html
|
||||
/// [`std::fs::read_to_string`]: https://doc.rust-lang.org/std/fs/fn.read_to_string.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` is not a file.
|
||||
/// * The current process lacks permissions to read `path`.
|
||||
/// * `path` does not point to an existing file.
|
||||
/// * The current process lacks permissions to read the file.
|
||||
/// * The contents of the file cannot be read as a UTF-8 string.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -30,5 +38,5 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn read_to_string<P: AsRef<Path>>(path: P) -> io::Result<String> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::read_to_string(path) }).await
|
||||
blocking::spawn(async move { std::fs::read_to_string(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Removes an existing, empty directory.
|
||||
/// Removes an empty directory.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::remove_dir`].
|
||||
///
|
||||
|
@ -12,10 +11,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` is not an empty directory.
|
||||
/// * The current process lacks permissions to remove directory at `path`.
|
||||
/// * `path` is not an existing and empty directory.
|
||||
/// * The current process lacks permissions to remove the directory.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -24,11 +24,11 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// fs::remove_dir("./some/dir").await?;
|
||||
/// fs::remove_dir("./some/directory").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::remove_dir(path) }).await
|
||||
blocking::spawn(async move { std::fs::remove_dir(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Removes an directory and all of its contents.
|
||||
/// Removes a directory and all of its contents.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::remove_dir_all`].
|
||||
///
|
||||
|
@ -12,10 +11,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` is not a directory.
|
||||
/// * The current process lacks permissions to remove directory at `path`.
|
||||
/// * `path` is not an existing and empty directory.
|
||||
/// * The current process lacks permissions to remove the directory.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -24,11 +24,11 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// fs::remove_dir_all("./some/dir").await?;
|
||||
/// fs::remove_dir_all("./some/directory").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::remove_dir_all(path) }).await
|
||||
blocking::spawn(async move { std::fs::remove_dir_all(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Removes a file from the filesystem.
|
||||
/// Removes a file.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::remove_file`].
|
||||
///
|
||||
|
@ -12,10 +11,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` is not a file.
|
||||
/// * The current process lacks permissions to remove file at `path`.
|
||||
/// * `path` does not point to an existing file.
|
||||
/// * The current process lacks permissions to remove the file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -30,5 +30,5 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn remove_file<P: AsRef<Path>>(path: P) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::remove_file(path) }).await
|
||||
blocking::spawn(async move { std::fs::remove_file(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Renames a file or directory to a new name, replacing the original if it already exists.
|
||||
/// Renames a file or directory to a new location.
|
||||
///
|
||||
/// If a file or directory already exists at the target location, it will be overwritten by this
|
||||
/// operation.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::rename`].
|
||||
///
|
||||
|
@ -12,11 +14,12 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `from` does not exist.
|
||||
/// * `from` does not point to an existing file or directory.
|
||||
/// * `from` and `to` are on different filesystems.
|
||||
/// * The current process lacks permissions to rename `from` to `to`.
|
||||
/// * The current process lacks permissions to do the rename operation.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -32,5 +35,5 @@ use crate::task::blocking;
|
|||
pub async fn rename<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
|
||||
let from = from.as_ref().to_owned();
|
||||
let to = to.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::rename(&from, &to) }).await
|
||||
blocking::spawn(async move { std::fs::rename(&from, &to) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::fs::Permissions;
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Changes the permissions on a file or directory.
|
||||
/// Changes the permissions of a file or directory.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::set_permissions`].
|
||||
///
|
||||
|
@ -12,10 +12,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` does not exist.
|
||||
/// * The current process lacks permissions to change attributes of `path`.
|
||||
/// * `path` does not point to an existing file or directory.
|
||||
/// * The current process lacks permissions to change attributes on the file or directory.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -30,7 +31,7 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn set_permissions<P: AsRef<Path>>(path: P, perm: fs::Permissions) -> io::Result<()> {
|
||||
pub async fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::set_permissions(path, perm) }).await
|
||||
blocking::spawn(async move { std::fs::set_permissions(path, perm) }).await
|
||||
}
|
||||
|
|
|
@ -1,21 +1,26 @@
|
|||
use std::fs::{self, Metadata};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::fs::Metadata;
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Queries the metadata for a path without following symlinks.
|
||||
/// Reads metadata for a path without following symbolic links.
|
||||
///
|
||||
/// If you want to follow symbolic links before reading metadata of the target file or directory,
|
||||
/// use [`metadata`] instead.
|
||||
///
|
||||
/// This function is an async version of [`std::fs::symlink_metadata`].
|
||||
///
|
||||
/// [`metadata`]: fn.metadata.html
|
||||
/// [`std::fs::symlink_metadata`]: https://doc.rust-lang.org/std/fs/fn.symlink_metadata.html
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * `path` does not exist.
|
||||
/// * The current process lacks permissions to query metadata for `path`.
|
||||
/// * `path` does not point to an existing file or directory.
|
||||
/// * The current process lacks permissions to read metadata for the path.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -30,5 +35,5 @@ use crate::task::blocking;
|
|||
/// ```
|
||||
pub async fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
|
||||
let path = path.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::symlink_metadata(path) }).await
|
||||
blocking::spawn(async move { std::fs::symlink_metadata(path) }).await
|
||||
}
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
use std::fs;
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io;
|
||||
use crate::task::blocking;
|
||||
|
||||
/// Writes a slice of bytes as the entire contents of a file.
|
||||
/// Writes a slice of bytes as the new contents of a file.
|
||||
///
|
||||
/// This function will create a file if it does not exist, and will entirely replace its contents
|
||||
/// if it does.
|
||||
|
@ -15,9 +14,11 @@ use crate::task::blocking;
|
|||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// An error will be returned in the following situations (not an exhaustive list):
|
||||
/// An error will be returned in the following situations:
|
||||
///
|
||||
/// * The current process lacks permissions to write into `path`.
|
||||
/// * The file's parent directory does not exist.
|
||||
/// * The current process lacks permissions to write to the file.
|
||||
/// * Some other I/O error occurred.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -26,12 +27,12 @@ use crate::task::blocking;
|
|||
/// #
|
||||
/// use async_std::fs;
|
||||
///
|
||||
/// fs::write("a.txt", b"Lorem ipsum").await?;
|
||||
/// fs::write("a.txt", b"Hello world!").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub async fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
let contents = contents.as_ref().to_owned();
|
||||
blocking::spawn(async move { fs::write(path, contents) }).await
|
||||
blocking::spawn(async move { std::fs::write(path, contents) }).await
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ impl<F: Future> Future for TimeoutFuture<F> {
|
|||
match self.as_mut().future().poll(cx) {
|
||||
Poll::Ready(v) => Poll::Ready(Ok(v)),
|
||||
Poll::Pending => match self.delay().poll(cx) {
|
||||
Poll::Ready(_) => Poll::Ready(Err(TimeoutError { _priv: () })),
|
||||
Poll::Ready(_) => Poll::Ready(Err(TimeoutError { _private: () })),
|
||||
Poll::Pending => Poll::Pending,
|
||||
},
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ impl<F: Future> Future for TimeoutFuture<F> {
|
|||
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||
pub struct TimeoutError {
|
||||
_priv: (),
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl Error for TimeoutError {}
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::task::{Context, Poll};
|
|||
///
|
||||
/// [`lines`]: trait.BufRead.html#method.lines
|
||||
/// [`BufRead`]: trait.BufRead.html
|
||||
/// [`std::io::Lines`]: https://doc.rust-lang.org/nightly/std/io/struct.Lines.html
|
||||
/// [`std::io::Lines`]: https://doc.rust-lang.org/std/io/struct.Lines.html
|
||||
#[derive(Debug)]
|
||||
pub struct Lines<R> {
|
||||
pub(crate) reader: R,
|
||||
|
|
|
@ -37,10 +37,10 @@ const DEFAULT_CAPACITY: usize = 8 * 1024;
|
|||
/// use async_std::io::BufReader;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = BufReader::new(File::open("a.txt").await?);
|
||||
/// let mut file = BufReader::new(File::open("a.txt").await?);
|
||||
///
|
||||
/// let mut line = String::new();
|
||||
/// f.read_line(&mut line).await?;
|
||||
/// file.read_line(&mut line).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
@ -134,8 +134,8 @@ impl<R> BufReader<R> {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::io::BufReader;
|
||||
///
|
||||
/// let mut f = BufReader::new(File::open("a.txt").await?);
|
||||
/// let inner = f.get_mut();
|
||||
/// let mut file = BufReader::new(File::open("a.txt").await?);
|
||||
/// let inner = file.get_mut();
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
|
|
@ -25,7 +25,7 @@ use crate::task::{Context, Poll};
|
|||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn empty() -> Empty {
|
||||
Empty { _priv: () }
|
||||
Empty { _private: () }
|
||||
}
|
||||
|
||||
/// A reader that contains no data.
|
||||
|
@ -34,7 +34,7 @@ pub fn empty() -> Empty {
|
|||
///
|
||||
/// [`sink`]: fn.sink.html
|
||||
pub struct Empty {
|
||||
_priv: (),
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl fmt::Debug for Empty {
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
pub mod prelude;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use std::io::{Error, ErrorKind, Result, SeekFrom};
|
||||
pub use std::io::{Error, ErrorKind, IoSlice, IoSliceMut, Result, SeekFrom};
|
||||
|
||||
pub use buf_read::{BufRead, Lines};
|
||||
pub use buf_reader::BufReader;
|
||||
|
|
|
@ -63,10 +63,10 @@ pub trait Read {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::open("a.txt").await?;
|
||||
/// let mut file = File::open("a.txt").await?;
|
||||
///
|
||||
/// let mut buf = vec![0; 1024];
|
||||
/// let n = f.read(&mut buf).await?;
|
||||
/// let n = file.read(&mut buf).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
@ -112,10 +112,10 @@ pub trait Read {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::open("a.txt").await?;
|
||||
/// let mut file = File::open("a.txt").await?;
|
||||
///
|
||||
/// let mut buf = Vec::new();
|
||||
/// f.read_to_end(&mut buf).await?;
|
||||
/// file.read_to_end(&mut buf).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
@ -149,10 +149,10 @@ pub trait Read {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::open("a.txt").await?;
|
||||
/// let mut file = File::open("a.txt").await?;
|
||||
///
|
||||
/// let mut buf = String::new();
|
||||
/// f.read_to_string(&mut buf).await?;
|
||||
/// file.read_to_string(&mut buf).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
@ -201,10 +201,10 @@ pub trait Read {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::open("a.txt").await?;
|
||||
/// let mut file = File::open("a.txt").await?;
|
||||
///
|
||||
/// let mut buf = vec![0; 10];
|
||||
/// f.read_exact(&mut buf).await?;
|
||||
/// file.read_exact(&mut buf).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
|
|
@ -49,9 +49,9 @@ pub trait Seek {
|
|||
/// use async_std::io::SeekFrom;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::open("a.txt").await?;
|
||||
/// let mut file = File::open("a.txt").await?;
|
||||
///
|
||||
/// let file_len = f.seek(SeekFrom::End(0)).await?;
|
||||
/// let file_len = file.seek(SeekFrom::End(0)).await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
|
|
@ -22,7 +22,7 @@ use crate::task::{Context, Poll};
|
|||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
pub fn sink() -> Sink {
|
||||
Sink { _priv: () }
|
||||
Sink { _private: () }
|
||||
}
|
||||
|
||||
/// A writer that consumes and drops all data.
|
||||
|
@ -31,7 +31,7 @@ pub fn sink() -> Sink {
|
|||
///
|
||||
/// [`sink`]: fn.sink.html
|
||||
pub struct Sink {
|
||||
_priv: (),
|
||||
_private: (),
|
||||
}
|
||||
|
||||
impl fmt::Debug for Sink {
|
||||
|
|
|
@ -56,9 +56,9 @@ pub trait Write {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::create("a.txt").await?;
|
||||
/// let mut file = File::create("a.txt").await?;
|
||||
///
|
||||
/// let n = f.write(b"hello world").await?;
|
||||
/// let n = file.write(b"hello world").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
@ -76,10 +76,10 @@ pub trait Write {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::create("a.txt").await?;
|
||||
/// let mut file = File::create("a.txt").await?;
|
||||
///
|
||||
/// f.write_all(b"hello world").await?;
|
||||
/// f.flush().await?;
|
||||
/// file.write_all(b"hello world").await?;
|
||||
/// file.flush().await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
@ -113,6 +113,8 @@ pub trait Write {
|
|||
/// an error is returned. This method will not return until the entire buffer has been
|
||||
/// successfully written or such an error occurs.
|
||||
///
|
||||
/// [`write`]: #tymethod.write
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
|
@ -121,9 +123,9 @@ pub trait Write {
|
|||
/// use async_std::fs::File;
|
||||
/// use async_std::prelude::*;
|
||||
///
|
||||
/// let mut f = File::create("a.txt").await?;
|
||||
/// let mut file = File::create("a.txt").await?;
|
||||
///
|
||||
/// f.write_all(b"hello world").await?;
|
||||
/// file.write_all(b"hello world").await?;
|
||||
/// #
|
||||
/// # Ok(()) }) }
|
||||
/// ```
|
||||
|
|
26
src/lib.rs
26
src/lib.rs
|
@ -1,13 +1,16 @@
|
|||
//! Async version of the Rust standard library.
|
||||
//!
|
||||
//! This crate is an async version of [`std`].
|
||||
//! Modules in this crate are organized in the same way as in the standard library, except blocking
|
||||
//! functions have been replaced with async functions and threads have been replaced with
|
||||
//! lightweight tasks.
|
||||
//!
|
||||
//! Higher-level documentation in the form of the book
|
||||
//! ["Async programming in Rust with async-std"][book]
|
||||
//! is available.
|
||||
//! More information, reading materials, and other resources:
|
||||
//!
|
||||
//! [`std`]: https://doc.rust-lang.org/std/index.html
|
||||
//! [book]: https://book.async.rs
|
||||
//! * [🌐 The async-std website](https://async.rs/)
|
||||
//! * [📖 The async-std book](https://book.async.rs)
|
||||
//! * [🐙 GitHub repository](https://github.com/async-rs/async-std)
|
||||
//! * [📒 List of code examples](https://github.com/async-rs/async-std/tree/master/examples)
|
||||
//! * [💬 Discord chat](https://discord.gg/JvZeVNe)
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
|
@ -23,8 +26,15 @@
|
|||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! See [here](https://github.com/async-rs/async-std/tree/master/examples)
|
||||
//! for more examples.
|
||||
//! # Features
|
||||
//!
|
||||
//! Unstable APIs in this crate are available when the `unstable` Cargo feature is enabled:
|
||||
//!
|
||||
//! ```toml
|
||||
//! [dependencies.async-std]
|
||||
//! version = "0.99"
|
||||
//! features = ["unstable"]
|
||||
//! ```
|
||||
|
||||
#![cfg_attr(feature = "docs", feature(doc_cfg))]
|
||||
#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
|
||||
|
|
|
@ -69,7 +69,6 @@ cfg_if! {
|
|||
fn custom_flags(&mut self, flags: i32) -> &mut Self;
|
||||
}
|
||||
} else {
|
||||
#[doc(inline)]
|
||||
pub use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,7 +51,6 @@ cfg_if! {
|
|||
fn into_raw_fd(self) -> RawFd;
|
||||
}
|
||||
} else {
|
||||
#[doc(inline)]
|
||||
pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,6 @@ cfg_if! {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
#[doc(inline)]
|
||||
pub use std::os::unix::net::SocketAddr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ cfg_if! {
|
|||
fn into_raw_handle(self) -> RawHandle;
|
||||
}
|
||||
} else {
|
||||
#[doc(inline)]
|
||||
pub use std::os::windows::io::{
|
||||
AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle, RawSocket,
|
||||
};
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
//! The async prelude.
|
||||
//!
|
||||
//! The prelude re-exports the most commonly used traits in this crate.
|
||||
//! The prelude re-exports most commonly used traits and macros from this crate.
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Import the prelude with:
|
||||
//!
|
||||
//! ```
|
||||
//! # #[allow(unused_imports)]
|
||||
//! use async_std::prelude::*;
|
||||
//! ```
|
||||
|
||||
#[doc(no_inline)]
|
||||
pub use crate::future::Future;
|
||||
|
|
Loading…
Reference in a new issue