2
0
Fork 1
mirror of https://github.com/async-rs/async-std.git synced 2025-04-16 05:16:44 +00:00

Merge remote-tracking branch 'upstream/master' into 342-stream-throttle

This commit is contained in:
Wouter Geraedts 2019-10-20 16:50:31 +02:00
commit ced5281b73
52 changed files with 961 additions and 1101 deletions

View file

@ -41,7 +41,7 @@ jobs:
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
command: test command: test
args: --all --doc --features unstable args: --all --features unstable
check_fmt_and_docs: check_fmt_and_docs:
name: Checking fmt and docs name: Checking fmt and docs

View file

@ -21,15 +21,15 @@ features = ["docs"]
rustdoc-args = ["--cfg", "feature=\"docs\""] rustdoc-args = ["--cfg", "feature=\"docs\""]
[features] [features]
docs = ["broadcaster"] docs = ["unstable"]
unstable = ["broadcaster"] unstable = ["broadcaster"]
[dependencies] [dependencies]
async-macros = "1.0.0" async-macros = "1.0.0"
async-task = "1.0.0" async-task = "1.0.0"
cfg-if = "0.1.9"
crossbeam-channel = "0.3.9" crossbeam-channel = "0.3.9"
crossbeam-deque = "0.7.1" crossbeam-deque = "0.7.1"
crossbeam-utils = "0.6.6"
futures-core-preview = "=0.3.0-alpha.19" futures-core-preview = "=0.3.0-alpha.19"
futures-io-preview = "=0.3.0-alpha.19" futures-io-preview = "=0.3.0-alpha.19"
futures-timer = "1.0.2" futures-timer = "1.0.2"

View file

@ -1,7 +1,5 @@
use std::future::Future; use std::future::Future;
use cfg_if::cfg_if;
use crate::io; use crate::io;
use crate::path::Path; use crate::path::Path;
use crate::task::blocking; use crate::task::blocking;
@ -113,22 +111,13 @@ impl DirBuilder {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::fs::DirBuilderExt;
use crate::os::unix::fs::DirBuilderExt;
} else if #[cfg(unix)] {
use std::os::unix::fs::DirBuilderExt;
}
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl DirBuilderExt for DirBuilder {
cfg_if! { fn mode(&mut self, mode: u32) -> &mut Self {
if #[cfg(any(unix, feature = "docs"))] { self.mode = Some(mode);
impl DirBuilderExt for DirBuilder { self
fn mode(&mut self, mode: u32) -> &mut Self {
self.mode = Some(mode);
self
}
} }
} }
} }

View file

@ -2,8 +2,6 @@ use std::ffi::OsString;
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;
use cfg_if::cfg_if;
use crate::fs::{FileType, Metadata}; use crate::fs::{FileType, Metadata};
use crate::io; use crate::io;
use crate::path::PathBuf; use crate::path::PathBuf;
@ -160,21 +158,12 @@ impl fmt::Debug for DirEntry {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::fs::DirEntryExt;
use crate::os::unix::fs::DirEntryExt;
} else if #[cfg(unix)] {
use std::os::unix::fs::DirEntryExt;
}
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl DirEntryExt for DirEntry {
cfg_if! { fn ino(&self) -> u64 {
if #[cfg(any(unix, feature = "docs"))] { self.0.ino()
impl DirEntryExt for DirEntry {
fn ino(&self) -> u64 {
self.0.ino()
}
} }
} }
} }

View file

@ -7,8 +7,6 @@ use std::pin::Pin;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use cfg_if::cfg_if;
use crate::fs::{Metadata, Permissions}; use crate::fs::{Metadata, Permissions};
use crate::future; use crate::future;
use crate::io::{self, Read, Seek, SeekFrom, Write}; use crate::io::{self, Read, Seek, SeekFrom, Write};
@ -401,67 +399,54 @@ impl From<std::fs::File> for File {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; impl AsRawFd for File {
} else if #[cfg(unix)] { fn as_raw_fd(&self) -> RawFd {
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; self.file.as_raw_fd()
} else if #[cfg(windows)] { }
use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
} }
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl FromRawFd for File {
cfg_if! { unsafe fn from_raw_fd(fd: RawFd) -> File {
if #[cfg(any(unix, feature = "docs"))] { std::fs::File::from_raw_fd(fd).into()
impl AsRawFd for File {
fn as_raw_fd(&self) -> RawFd {
self.file.as_raw_fd()
}
} }
}
impl FromRawFd for File { impl IntoRawFd for File {
unsafe fn from_raw_fd(fd: RawFd) -> File { fn into_raw_fd(self) -> RawFd {
std::fs::File::from_raw_fd(fd).into() let file = self.file.clone();
} drop(self);
} Arc::try_unwrap(file)
.expect("cannot acquire ownership of the file handle after drop")
impl IntoRawFd for File { .into_raw_fd()
fn into_raw_fd(self) -> RawFd {
let file = self.file.clone();
drop(self);
Arc::try_unwrap(file)
.expect("cannot acquire ownership of the file handle after drop")
.into_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(windows)))] cfg_windows! {
cfg_if! { use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] {
impl AsRawHandle for File {
fn as_raw_handle(&self) -> RawHandle {
self.file.as_raw_handle()
}
}
impl FromRawHandle for File { impl AsRawHandle for File {
unsafe fn from_raw_handle(handle: RawHandle) -> File { fn as_raw_handle(&self) -> RawHandle {
std::fs::File::from_raw_handle(handle).into() self.file.as_raw_handle()
}
} }
}
impl IntoRawHandle for File { impl FromRawHandle for File {
fn into_raw_handle(self) -> RawHandle { unsafe fn from_raw_handle(handle: RawHandle) -> File {
let file = self.file.clone(); std::fs::File::from_raw_handle(handle).into()
drop(self); }
Arc::try_unwrap(file) }
.expect("cannot acquire ownership of the file handle after drop")
.into_raw_handle() impl IntoRawHandle for File {
} fn into_raw_handle(self) -> RawHandle {
let file = self.file.clone();
drop(self);
Arc::try_unwrap(file)
.expect("cannot acquire ownership of the file handle after drop")
.into_raw_handle()
} }
} }
} }

View file

@ -1,86 +1,84 @@
use cfg_if::cfg_if; cfg_not_docs! {
pub use std::fs::FileType;
}
cfg_if! { cfg_docs! {
if #[cfg(feature = "docs")] { /// The type of a file or directory.
/// 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.
/// ///
/// A file type is returned by [`Metadata::file_type`]. /// If this file type represents a symbolic link, this method returns `false`.
/// ///
/// Note that file types are mutually exclusive, i.e. at most one of methods [`is_dir`], /// # Examples
/// [`is_file`], and [`is_symlink`] can return `true`.
/// ///
/// This type is a re-export of [`std::fs::FileType`]. /// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs;
/// ///
/// [`Metadata::file_type`]: struct.Metadata.html#method.file_type /// let file_type = fs::metadata(".").await?.file_type();
/// [`is_dir`]: #method.is_dir /// println!("{:?}", file_type.is_dir());
/// [`is_file`]: #method.is_file /// #
/// [`is_symlink`]: #method.is_symlink /// # Ok(()) }) }
/// [`std::fs::FileType`]: https://doc.rust-lang.org/std/fs/struct.FileType.html /// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub fn is_dir(&self) -> bool {
pub struct FileType { unimplemented!()
_private: (),
} }
impl FileType { /// Returns `true` if this file type represents a regular file.
/// Returns `true` if this file type represents a regular directory. ///
/// /// If this file type represents a symbolic link, this method returns `false`.
/// If this file type represents a symbolic link, this method returns `false`. ///
/// /// # Examples
/// # Examples ///
/// /// ```no_run
/// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// #
/// # /// use async_std::fs;
/// use async_std::fs; ///
/// /// let file_type = fs::metadata("a.txt").await?.file_type();
/// let file_type = fs::metadata(".").await?.file_type(); /// println!("{:?}", file_type.is_file());
/// println!("{:?}", file_type.is_dir()); /// #
/// # /// # Ok(()) }) }
/// # Ok(()) }) } /// ```
/// ``` pub fn is_file(&self) -> bool {
pub fn is_dir(&self) -> bool { unimplemented!()
unimplemented!() }
}
/// Returns `true` if this file type represents a symbolic link.
/// Returns `true` if this file type represents a regular file. ///
/// /// # Examples
/// If this file type represents a symbolic link, this method returns `false`. ///
/// /// ```no_run
/// # Examples /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// /// #
/// ```no_run /// use async_std::fs;
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { ///
/// # /// let file_type = fs::metadata("a.txt").await?.file_type();
/// use async_std::fs; /// println!("{:?}", file_type.is_symlink());
/// /// #
/// let file_type = fs::metadata("a.txt").await?.file_type(); /// # Ok(()) }) }
/// println!("{:?}", file_type.is_file()); /// ```
/// # pub fn is_symlink(&self) -> bool {
/// # Ok(()) }) } unimplemented!()
/// ```
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;
} }
} }

View file

@ -1,5 +1,3 @@
use cfg_if::cfg_if;
use crate::io; use crate::io;
use crate::path::Path; use crate::path::Path;
use crate::task::blocking; use crate::task::blocking;
@ -39,193 +37,193 @@ pub async fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
blocking::spawn(move || std::fs::metadata(path)).await blocking::spawn(move || std::fs::metadata(path)).await
} }
cfg_if! { cfg_not_docs! {
if #[cfg(feature = "docs")] { pub use std::fs::Metadata;
use std::time::SystemTime; }
use crate::fs::{FileType, Permissions}; cfg_docs! {
use std::time::SystemTime;
/// Metadata for a file or directory. 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.
/// ///
/// Metadata is returned by [`metadata`] and [`symlink_metadata`]. /// # Examples
/// ///
/// This type is a re-export of [`std::fs::Metadata`]. /// ```no_run
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// #
/// use async_std::fs;
/// ///
/// [`metadata`]: fn.metadata.html /// let metadata = fs::metadata("a.txt").await?;
/// [`symlink_metadata`]: fn.symlink_metadata.html /// println!("{:?}", metadata.file_type());
/// [`is_dir`]: #method.is_dir /// #
/// [`is_file`]: #method.is_file /// # Ok(()) }) }
/// [`std::fs::Metadata`]: https://doc.rust-lang.org/std/fs/struct.Metadata.html /// ```
#[derive(Clone, Debug)] pub fn file_type(&self) -> FileType {
pub struct Metadata { unimplemented!()
_private: (),
} }
impl Metadata { /// Returns `true` if this metadata is for a regular directory.
/// Returns the file type from this metadata. ///
/// /// If this metadata is for a symbolic link, this method returns `false`.
/// # Examples ///
/// /// # Examples
/// ```no_run ///
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// ```no_run
/// # /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// use async_std::fs; /// #
/// /// use async_std::fs;
/// let metadata = fs::metadata("a.txt").await?; ///
/// println!("{:?}", metadata.file_type()); /// let metadata = fs::metadata(".").await?;
/// # /// println!("{:?}", metadata.is_dir());
/// # Ok(()) }) } /// #
/// ``` /// # Ok(()) }) }
pub fn file_type(&self) -> FileType { /// ```
unimplemented!() pub fn is_dir(&self) -> bool {
} unimplemented!()
}
/// Returns `true` if this metadata is for a regular directory.
/// /// Returns `true` if this metadata is for a regular file.
/// If this metadata is for a symbolic link, this method returns `false`. ///
/// /// If this metadata is for a symbolic link, this method returns `false`.
/// # Examples ///
/// /// # Examples
/// ```no_run ///
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// ```no_run
/// # /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// use async_std::fs; /// #
/// /// use async_std::fs;
/// let metadata = fs::metadata(".").await?; ///
/// println!("{:?}", metadata.is_dir()); /// let metadata = fs::metadata("a.txt").await?;
/// # /// println!("{:?}", metadata.is_file());
/// # Ok(()) }) } /// #
/// ``` /// # Ok(()) }) }
pub fn is_dir(&self) -> bool { /// ```
unimplemented!() pub fn is_file(&self) -> bool {
} unimplemented!()
}
/// Returns `true` if this metadata is for a regular file.
/// /// Returns the file size in bytes.
/// If this metadata is for a symbolic link, this method returns `false`. ///
/// /// # Examples
/// # Examples ///
/// /// ```no_run
/// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// #
/// # /// use async_std::fs;
/// use async_std::fs; ///
/// /// let metadata = fs::metadata("a.txt").await?;
/// let metadata = fs::metadata("a.txt").await?; /// println!("{}", metadata.len());
/// println!("{:?}", metadata.is_file()); /// #
/// # /// # Ok(()) }) }
/// # Ok(()) }) } /// ```
/// ``` pub fn len(&self) -> u64 {
pub fn is_file(&self) -> bool { unimplemented!()
unimplemented!() }
}
/// Returns the permissions from this metadata.
/// Returns the file size in bytes. ///
/// /// # Examples
/// # Examples ///
/// /// ```no_run
/// ```no_run /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// #
/// # /// use async_std::fs;
/// use async_std::fs; ///
/// /// let metadata = fs::metadata("a.txt").await?;
/// let metadata = fs::metadata("a.txt").await?; /// println!("{:?}", metadata.permissions());
/// println!("{}", metadata.len()); /// #
/// # /// # Ok(()) }) }
/// # Ok(()) }) } /// ```
/// ``` pub fn permissions(&self) -> Permissions {
pub fn len(&self) -> u64 { unimplemented!()
unimplemented!() }
}
/// Returns the last modification time.
/// Returns the permissions from this metadata. ///
/// /// # Errors
/// # Examples ///
/// /// This data may not be available on all platforms, in which case an error will be
/// ```no_run /// returned.
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { ///
/// # /// # Examples
/// use async_std::fs; ///
/// /// ```no_run
/// let metadata = fs::metadata("a.txt").await?; /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// println!("{:?}", metadata.permissions()); /// #
/// # /// use async_std::fs;
/// # Ok(()) }) } ///
/// ``` /// let metadata = fs::metadata("a.txt").await?;
pub fn permissions(&self) -> Permissions { /// println!("{:?}", metadata.modified());
unimplemented!() /// #
} /// # Ok(()) }) }
/// ```
/// Returns the last modification time. pub fn modified(&self) -> io::Result<SystemTime> {
/// unimplemented!()
/// # Errors }
///
/// This data may not be available on all platforms, in which case an error will be /// Returns the last access time.
/// returned. ///
/// /// # Errors
/// # Examples ///
/// /// This data may not be available on all platforms, in which case an error will be
/// ```no_run /// returned.
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { ///
/// # /// # Examples
/// use async_std::fs; ///
/// /// ```no_run
/// let metadata = fs::metadata("a.txt").await?; /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// println!("{:?}", metadata.modified()); /// #
/// # /// use async_std::fs;
/// # Ok(()) }) } ///
/// ``` /// let metadata = fs::metadata("a.txt").await?;
pub fn modified(&self) -> io::Result<SystemTime> { /// println!("{:?}", metadata.accessed());
unimplemented!() /// #
} /// # Ok(()) }) }
/// ```
/// Returns the last access time. pub fn accessed(&self) -> io::Result<SystemTime> {
/// unimplemented!()
/// # Errors }
///
/// This data may not be available on all platforms, in which case an error will be /// Returns the creation time.
/// returned. ///
/// /// # Errors
/// # Examples ///
/// /// This data may not be available on all platforms, in which case an error will be
/// ```no_run /// returned.
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { ///
/// # /// # Examples
/// use async_std::fs; ///
/// /// ```no_run
/// let metadata = fs::metadata("a.txt").await?; /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// println!("{:?}", metadata.accessed()); /// #
/// # /// use async_std::fs;
/// # Ok(()) }) } ///
/// ``` /// let metadata = fs::metadata("a.txt").await?;
pub fn accessed(&self) -> io::Result<SystemTime> { /// println!("{:?}", metadata.created());
unimplemented!() /// #
} /// # Ok(()) }) }
/// ```
/// Returns the creation time. pub fn created(&self) -> io::Result<SystemTime> {
/// unimplemented!()
/// # 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 async_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;
} }
} }

View file

@ -1,7 +1,5 @@
use std::future::Future; use std::future::Future;
use cfg_if::cfg_if;
use crate::fs::File; use crate::fs::File;
use crate::io; use crate::io;
use crate::path::Path; use crate::path::Path;
@ -296,27 +294,18 @@ impl Default for OpenOptions {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::fs::OpenOptionsExt;
use crate::os::unix::fs::OpenOptionsExt;
} else if #[cfg(unix)] {
use std::os::unix::fs::OpenOptionsExt;
}
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl OpenOptionsExt for OpenOptions {
cfg_if! { fn mode(&mut self, mode: u32) -> &mut Self {
if #[cfg(any(unix, feature = "docs"))] { self.0.mode(mode);
impl OpenOptionsExt for OpenOptions { self
fn mode(&mut self, mode: u32) -> &mut Self { }
self.0.mode(mode);
self
}
fn custom_flags(&mut self, flags: i32) -> &mut Self { fn custom_flags(&mut self, flags: i32) -> &mut Self {
self.0.custom_flags(flags); self.0.custom_flags(flags);
self self
}
} }
} }
} }

View file

@ -1,58 +1,56 @@
use cfg_if::cfg_if; cfg_not_docs! {
pub use std::fs::Permissions;
}
cfg_if! { cfg_docs! {
if #[cfg(feature = "docs")] { /// A set of permissions on a file or directory.
/// 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.
/// ///
/// This type is a re-export of [`std::fs::Permissions`]. /// # Examples
/// ///
/// [`std::fs::Permissions`]: https://doc.rust-lang.org/std/fs/struct.Permissions.html /// ```no_run
#[derive(Clone, PartialEq, Eq, Debug)] /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
pub struct Permissions { /// #
_private: (), /// use async_std::fs;
///
/// let perm = fs::metadata("a.txt").await?.permissions();
/// println!("{:?}", perm.readonly());
/// #
/// # Ok(()) }) }
/// ```
pub fn readonly(&self) -> bool {
unimplemented!()
} }
impl Permissions { /// Configures the read-only flag.
/// Returns the read-only flag. ///
/// /// [`fs::set_permissions`]: fn.set_permissions.html
/// # Examples ///
/// /// # Examples
/// ```no_run ///
/// # fn main() -> std::io::Result<()> { async_std::task::block_on(async { /// ```no_run
/// # /// # fn main() -> std::io::Result<()> { async_std::task::block_on(async {
/// use async_std::fs; /// #
/// /// use async_std::fs;
/// let perm = fs::metadata("a.txt").await?.permissions(); ///
/// println!("{:?}", perm.readonly()); /// let mut perm = fs::metadata("a.txt").await?.permissions();
/// # /// perm.set_readonly(true);
/// # Ok(()) }) } /// fs::set_permissions("a.txt", perm).await?;
/// ``` /// #
pub fn readonly(&self) -> bool { /// # Ok(()) }) }
unimplemented!() /// ```
} pub fn set_readonly(&mut self, readonly: 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;
} }
} }

View file

@ -1,15 +1,9 @@
use crate::utils::extension_trait;
cfg_if::cfg_if! {
if #[cfg(feature = "docs")] {
use std::pin::Pin;
use std::ops::{Deref, DerefMut};
use crate::task::{Context, Poll};
}
}
extension_trait! { extension_trait! {
use std::pin::Pin;
use std::ops::{Deref, DerefMut};
use crate::task::{Context, Poll};
#[doc = r#" #[doc = r#"
A future represents an asynchronous computation. A future represents an asynchronous computation.

View file

@ -30,7 +30,7 @@ use crate::future::Future;
/// } /// }
/// } /// }
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
pub trait IntoFuture { pub trait IntoFuture {
/// The type of value produced on completion. /// The type of value produced on completion.

View file

@ -44,12 +44,6 @@
#[doc(inline)] #[doc(inline)]
pub use async_macros::{join, try_join}; pub use async_macros::{join, try_join};
#[doc(inline)]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
pub use async_macros::{select, try_select};
use cfg_if::cfg_if;
pub use future::Future; pub use future::Future;
pub use pending::pending; pub use pending::pending;
pub use poll_fn::poll_fn; pub use poll_fn::poll_fn;
@ -62,10 +56,10 @@ mod poll_fn;
mod ready; mod ready;
mod timeout; mod timeout;
cfg_if! { cfg_unstable! {
if #[cfg(any(feature = "unstable", feature = "docs"))] { #[doc(inline)]
mod into_future; pub use async_macros::{select, try_select};
pub use into_future::IntoFuture; pub use into_future::IntoFuture;
} mod into_future;
} }

View file

@ -12,19 +12,12 @@ use read_until::ReadUntilFuture;
use std::mem; use std::mem;
use std::pin::Pin; use std::pin::Pin;
use cfg_if::cfg_if;
use crate::io; use crate::io;
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
use crate::utils::extension_trait;
cfg_if! {
if #[cfg(feature = "docs")] {
use std::ops::{Deref, DerefMut};
}
}
extension_trait! { extension_trait! {
use std::ops::{Deref, DerefMut};
#[doc = r#" #[doc = r#"
Allows reading from a buffered byte stream. Allows reading from a buffered byte stream.

View file

@ -13,23 +13,17 @@ use read_to_end::{read_to_end_internal, ReadToEndFuture};
use read_to_string::ReadToStringFuture; use read_to_string::ReadToStringFuture;
use read_vectored::ReadVectoredFuture; use read_vectored::ReadVectoredFuture;
use cfg_if::cfg_if;
use std::mem; use std::mem;
use crate::io::IoSliceMut; use crate::io::IoSliceMut;
use crate::utils::extension_trait;
cfg_if! {
if #[cfg(feature = "docs")] {
use std::pin::Pin;
use std::ops::{Deref, DerefMut};
use crate::io;
use crate::task::{Context, Poll};
}
}
extension_trait! { extension_trait! {
use std::pin::Pin;
use std::ops::{Deref, DerefMut};
use crate::io;
use crate::task::{Context, Poll};
#[doc = r#" #[doc = r#"
Allows reading from a byte stream. Allows reading from a byte stream.

View file

@ -1,19 +1,16 @@
use std::pin::Pin; mod seek;
use cfg_if::cfg_if; use seek::SeekFuture;
use crate::future::Future; use crate::io::SeekFrom;
use crate::io::{self, SeekFrom};
use crate::task::{Context, Poll};
use crate::utils::extension_trait;
cfg_if! {
if #[cfg(feature = "docs")] {
use std::ops::{Deref, DerefMut};
}
}
extension_trait! { extension_trait! {
use std::ops::{Deref, DerefMut};
use std::pin::Pin;
use crate::io;
use crate::task::{Context, Poll};
#[doc = r#" #[doc = r#"
Allows seeking through a byte stream. Allows seeking through a byte stream.
@ -114,19 +111,3 @@ extension_trait! {
} }
} }
} }
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct SeekFuture<'a, T: Unpin + ?Sized> {
seeker: &'a mut T,
pos: SeekFrom,
}
impl<T: SeekExt + Unpin + ?Sized> Future for SeekFuture<'_, T> {
type Output = io::Result<u64>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let pos = self.pos;
Pin::new(&mut *self.seeker).poll_seek(cx, pos)
}
}

21
src/io/seek/seek.rs Normal file
View file

@ -0,0 +1,21 @@
use std::pin::Pin;
use crate::future::Future;
use crate::io::{self, Seek, SeekFrom};
use crate::task::{Context, Poll};
#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct SeekFuture<'a, T: Unpin + ?Sized> {
pub(crate) seeker: &'a mut T,
pub(crate) pos: SeekFrom,
}
impl<T: Seek + Unpin + ?Sized> Future for SeekFuture<'_, T> {
type Output = io::Result<u64>;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let pos = self.pos;
Pin::new(&mut *self.seeker).poll_seek(cx, pos)
}
}

View file

@ -1,8 +1,6 @@
use std::pin::Pin; use std::pin::Pin;
use std::sync::Mutex; use std::sync::Mutex;
use cfg_if::cfg_if;
use crate::future::Future; use crate::future::Future;
use crate::io::{self, Write}; use crate::io::{self, Write};
use crate::task::{blocking, Context, JoinHandle, Poll}; use crate::task::{blocking, Context, JoinHandle, Poll};
@ -162,35 +160,22 @@ impl Write for Stderr {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, RawFd};
use crate::os::windows::io::{AsRawHandle, RawHandle};
} else if #[cfg(unix)] {
use std::os::unix::io::{AsRawFd, RawFd};
} else if #[cfg(windows)] {
use std::os::windows::io::{AsRawHandle, RawHandle};
}
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl AsRawFd for Stderr {
cfg_if! { fn as_raw_fd(&self) -> RawFd {
if #[cfg(any(unix, feature = "docs"))] { std::io::stderr().as_raw_fd()
impl AsRawFd for Stderr {
fn as_raw_fd(&self) -> RawFd {
std::io::stderr().as_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(unix)))] cfg_windows! {
cfg_if! { use crate::os::windows::io::{AsRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] {
impl AsRawHandle for Stderr { impl AsRawHandle for Stderr {
fn as_raw_handle(&self) -> RawHandle { fn as_raw_handle(&self) -> RawHandle {
std::io::stderr().as_raw_handle() std::io::stderr().as_raw_handle()
}
} }
} }
} }

View file

@ -1,8 +1,6 @@
use std::pin::Pin; use std::pin::Pin;
use std::sync::Mutex; use std::sync::Mutex;
use cfg_if::cfg_if;
use crate::future::{self, Future}; use crate::future::{self, Future};
use crate::io::{self, Read}; use crate::io::{self, Read};
use crate::task::{blocking, Context, JoinHandle, Poll}; use crate::task::{blocking, Context, JoinHandle, Poll};
@ -186,35 +184,22 @@ impl Read for Stdin {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, RawFd};
use crate::os::windows::io::{AsRawHandle, RawHandle};
} else if #[cfg(unix)] {
use std::os::unix::io::{AsRawFd, RawFd};
} else if #[cfg(windows)] {
use std::os::windows::io::{AsRawHandle, RawHandle};
}
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl AsRawFd for Stdin {
cfg_if! { fn as_raw_fd(&self) -> RawFd {
if #[cfg(any(unix, feature = "docs"))] { std::io::stdin().as_raw_fd()
impl AsRawFd for Stdin {
fn as_raw_fd(&self) -> RawFd {
std::io::stdin().as_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(unix)))] cfg_windows! {
cfg_if! { use crate::os::windows::io::{AsRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] {
impl AsRawHandle for Stdin { impl AsRawHandle for Stdin {
fn as_raw_handle(&self) -> RawHandle { fn as_raw_handle(&self) -> RawHandle {
std::io::stdin().as_raw_handle() std::io::stdin().as_raw_handle()
}
} }
} }
} }

View file

@ -1,8 +1,6 @@
use std::pin::Pin; use std::pin::Pin;
use std::sync::Mutex; use std::sync::Mutex;
use cfg_if::cfg_if;
use crate::future::Future; use crate::future::Future;
use crate::io::{self, Write}; use crate::io::{self, Write};
use crate::task::{blocking, Context, JoinHandle, Poll}; use crate::task::{blocking, Context, JoinHandle, Poll};
@ -162,35 +160,22 @@ impl Write for Stdout {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, RawFd};
use crate::os::windows::io::{AsRawHandle, RawHandle};
} else if #[cfg(unix)] {
use std::os::unix::io::{AsRawFd, RawFd};
} else if #[cfg(windows)] {
use std::os::windows::io::{AsRawHandle, RawHandle};
}
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl AsRawFd for Stdout {
cfg_if! { fn as_raw_fd(&self) -> RawFd {
if #[cfg(any(unix, feature = "docs"))] { std::io::stdout().as_raw_fd()
impl AsRawFd for Stdout {
fn as_raw_fd(&self) -> RawFd {
std::io::stdout().as_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(unix)))] cfg_windows! {
cfg_if! { use crate::os::windows::io::{AsRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] {
impl AsRawHandle for Stdout { impl AsRawHandle for Stdout {
fn as_raw_handle(&self) -> RawHandle { fn as_raw_handle(&self) -> RawHandle {
std::io::stdout().as_raw_handle() std::io::stdout().as_raw_handle()
}
} }
} }
} }

View file

@ -10,22 +10,14 @@ use write_all::WriteAllFuture;
use write_fmt::WriteFmtFuture; use write_fmt::WriteFmtFuture;
use write_vectored::WriteVectoredFuture; use write_vectored::WriteVectoredFuture;
use cfg_if::cfg_if; use crate::io::{self, IoSlice};
use crate::io::IoSlice;
use crate::utils::extension_trait;
use crate::io;
cfg_if! {
if #[cfg(feature = "docs")] {
use std::pin::Pin;
use std::ops::{Deref, DerefMut};
use crate::task::{Context, Poll};
}
}
extension_trait! { extension_trait! {
use std::pin::Pin;
use std::ops::{Deref, DerefMut};
use crate::task::{Context, Poll};
#[doc = r#" #[doc = r#"
Allows writing to a byte stream. Allows writing to a byte stream.

View file

@ -48,7 +48,8 @@
#![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")] #![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")]
#![recursion_limit = "1024"] #![recursion_limit = "1024"]
use cfg_if::cfg_if; #[macro_use]
mod utils;
pub mod fs; pub mod fs;
pub mod future; pub mod future;
@ -61,26 +62,19 @@ pub mod stream;
pub mod sync; pub mod sync;
pub mod task; pub mod task;
cfg_if! { cfg_unstable! {
if #[cfg(any(feature = "unstable", feature = "docs"))] { pub mod pin;
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub mod process;
pub mod pin;
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
pub mod process;
mod unit; mod unit;
mod vec; mod vec;
mod result; mod result;
mod option; mod option;
mod string; mod string;
mod collections; mod collections;
}
#[doc(inline)]
pub use std::{write, writeln};
} }
mod macros; mod macros;
pub(crate) mod utils;
#[cfg(any(feature = "unstable", feature = "docs"))]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[doc(inline)]
pub use std::{write, writeln};

View file

@ -43,7 +43,7 @@
/// # /// #
/// # }) /// # })
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[macro_export] #[macro_export]
macro_rules! print { macro_rules! print {
@ -81,7 +81,7 @@ macro_rules! print {
/// # /// #
/// # }) /// # })
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[macro_export] #[macro_export]
macro_rules! println { macro_rules! println {
@ -119,7 +119,7 @@ macro_rules! println {
/// # /// #
/// # }) /// # })
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[macro_export] #[macro_export]
macro_rules! eprint { macro_rules! eprint {
@ -153,7 +153,7 @@ macro_rules! eprint {
/// # /// #
/// # }) /// # })
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[macro_export] #[macro_export]
macro_rules! eprintln { macro_rules! eprintln {

View file

@ -3,24 +3,22 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6};
use std::pin::Pin; use std::pin::Pin;
use cfg_if::cfg_if;
use crate::future::Future; use crate::future::Future;
use crate::io; use crate::io;
use crate::task::{blocking, Context, JoinHandle, Poll}; use crate::task::{blocking, Context, JoinHandle, Poll};
cfg_if! { cfg_not_docs! {
if #[cfg(feature = "docs")] { macro_rules! ret {
#[doc(hidden)] (impl Future<Output = $out:ty>, $fut:ty) => ($fut);
pub struct ImplFuture<T>(std::marker::PhantomData<T>); }
}
macro_rules! ret { cfg_docs! {
(impl Future<Output = $out:ty>, $fut:ty) => (ImplFuture<$out>); #[doc(hidden)]
} pub struct ImplFuture<T>(std::marker::PhantomData<T>);
} else {
macro_rules! ret { macro_rules! ret {
(impl Future<Output = $out:ty>, $fut:ty) => ($fut); (impl Future<Output = $out:ty>, $fut:ty) => (ImplFuture<$out>);
}
} }
} }

View file

@ -1,13 +1,10 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use std::pin::Pin; use std::pin::Pin;
use cfg_if::cfg_if;
use super::TcpStream;
use crate::future::{self, Future}; use crate::future::{self, Future};
use crate::io; use crate::io;
use crate::net::driver::Watcher; use crate::net::driver::Watcher;
use crate::net::ToSocketAddrs; use crate::net::{TcpStream, ToSocketAddrs};
use crate::stream::Stream; use crate::stream::Stream;
use crate::task::{Context, Poll}; use crate::task::{Context, Poll};
@ -213,59 +210,46 @@ impl From<std::net::TcpListener> for TcpListener {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
// use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; impl AsRawFd for TcpListener {
} else if #[cfg(unix)] { fn as_raw_fd(&self) -> RawFd {
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; self.watcher.get_ref().as_raw_fd()
} else if #[cfg(windows)] { }
// use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
} }
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl FromRawFd for TcpListener {
cfg_if! { unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
if #[cfg(any(unix, feature = "docs"))] { std::net::TcpListener::from_raw_fd(fd).into()
impl AsRawFd for TcpListener {
fn as_raw_fd(&self) -> RawFd {
self.watcher.get_ref().as_raw_fd()
}
} }
}
impl FromRawFd for TcpListener { impl IntoRawFd for TcpListener {
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener { fn into_raw_fd(self) -> RawFd {
std::net::TcpListener::from_raw_fd(fd).into() self.watcher.into_inner().into_raw_fd()
}
}
impl IntoRawFd for TcpListener {
fn into_raw_fd(self) -> RawFd {
self.watcher.into_inner().into_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(windows)))] cfg_windows! {
cfg_if! { // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] { //
// impl AsRawSocket for TcpListener { // impl AsRawSocket for TcpListener {
// fn as_raw_socket(&self) -> RawSocket { // fn as_raw_socket(&self) -> RawSocket {
// self.raw_socket // self.raw_socket
// } // }
// } // }
// //
// impl FromRawSocket for TcpListener { // impl FromRawSocket for TcpListener {
// unsafe fn from_raw_socket(handle: RawSocket) -> TcpListener { // unsafe fn from_raw_socket(handle: RawSocket) -> TcpListener {
// net::TcpListener::from_raw_socket(handle).try_into().unwrap() // net::TcpListener::from_raw_socket(handle).try_into().unwrap()
// } // }
// } // }
// //
// impl IntoRawSocket for TcpListener { // impl IntoRawSocket for TcpListener {
// fn into_raw_socket(self) -> RawSocket { // fn into_raw_socket(self) -> RawSocket {
// self.raw_socket // self.raw_socket
// } // }
// } // }
}
} }

View file

@ -2,8 +2,6 @@ use std::io::{IoSlice, IoSliceMut, Read as _, Write as _};
use std::net::SocketAddr; use std::net::SocketAddr;
use std::pin::Pin; use std::pin::Pin;
use cfg_if::cfg_if;
use crate::future; use crate::future;
use crate::io::{self, Read, Write}; use crate::io::{self, Read, Write};
use crate::net::driver::Watcher; use crate::net::driver::Watcher;
@ -367,59 +365,46 @@ impl From<std::net::TcpStream> for TcpStream {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
// use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; impl AsRawFd for TcpStream {
} else if #[cfg(unix)] { fn as_raw_fd(&self) -> RawFd {
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; self.watcher.get_ref().as_raw_fd()
} else if #[cfg(windows)] { }
// use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
} }
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl FromRawFd for TcpStream {
cfg_if! { unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
if #[cfg(any(unix, feature = "docs"))] { std::net::TcpStream::from_raw_fd(fd).into()
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.watcher.get_ref().as_raw_fd()
}
} }
}
impl FromRawFd for TcpStream { impl IntoRawFd for TcpStream {
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream { fn into_raw_fd(self) -> RawFd {
std::net::TcpStream::from_raw_fd(fd).into() self.watcher.into_inner().into_raw_fd()
}
}
impl IntoRawFd for TcpStream {
fn into_raw_fd(self) -> RawFd {
self.watcher.into_inner().into_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(windows)))] cfg_windows! {
cfg_if! { // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] { //
// impl AsRawSocket for TcpStream { // impl AsRawSocket for TcpStream {
// fn as_raw_socket(&self) -> RawSocket { // fn as_raw_socket(&self) -> RawSocket {
// self.raw_socket // self.raw_socket
// } // }
// } // }
// //
// impl FromRawSocket for TcpStream { // impl FromRawSocket for TcpStream {
// unsafe fn from_raw_socket(handle: RawSocket) -> TcpStream { // unsafe fn from_raw_socket(handle: RawSocket) -> TcpStream {
// net::TcpStream::from_raw_socket(handle).try_into().unwrap() // net::TcpStream::from_raw_socket(handle).try_into().unwrap()
// } // }
// } // }
// //
// impl IntoRawSocket for TcpListener { // impl IntoRawSocket for TcpListener {
// fn into_raw_socket(self) -> RawSocket { // fn into_raw_socket(self) -> RawSocket {
// self.raw_socket // self.raw_socket
// } // }
// } // }
}
} }

View file

@ -1,7 +1,5 @@
use std::io; use std::io;
use std::net::SocketAddr; use std::net::SocketAddr;
use cfg_if::cfg_if;
use std::net::{Ipv4Addr, Ipv6Addr}; use std::net::{Ipv4Addr, Ipv6Addr};
use crate::future; use crate::future;
@ -463,61 +461,46 @@ impl From<std::net::UdpSocket> for UdpSocket {
} }
} }
cfg_if! { cfg_unix! {
if #[cfg(feature = "docs")] { use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
// use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; impl AsRawFd for UdpSocket {
} else if #[cfg(unix)] { fn as_raw_fd(&self) -> RawFd {
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; self.watcher.get_ref().as_raw_fd()
} else if #[cfg(windows)] { }
// use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
} }
}
#[cfg_attr(feature = "docs", doc(cfg(unix)))] impl FromRawFd for UdpSocket {
cfg_if! { unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket {
if #[cfg(any(unix, feature = "docs"))] { std::net::UdpSocket::from_raw_fd(fd).into()
impl AsRawFd for UdpSocket {
fn as_raw_fd(&self) -> RawFd {
self.watcher.get_ref().as_raw_fd()
}
} }
}
impl FromRawFd for UdpSocket { impl IntoRawFd for UdpSocket {
unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { fn into_raw_fd(self) -> RawFd {
std::net::UdpSocket::from_raw_fd(fd).into() self.watcher.into_inner().into_raw_fd()
}
}
impl IntoRawFd for UdpSocket {
fn into_raw_fd(self) -> RawFd {
self.watcher.into_inner().into_raw_fd()
}
} }
} }
} }
#[cfg_attr(feature = "docs", doc(cfg(windows)))] cfg_windows! {
cfg_if! { // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle};
if #[cfg(any(windows, feature = "docs"))] { //
// use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket}; // impl AsRawSocket for UdpSocket {
// // fn as_raw_socket(&self) -> RawSocket {
// impl AsRawSocket for UdpSocket { // self.raw_socket
// fn as_raw_socket(&self) -> RawSocket { // }
// self.raw_socket // }
// } //
// } // impl FromRawSocket for UdpSocket {
// // unsafe fn from_raw_socket(handle: RawSocket) -> UdpSocket {
// impl FromRawSocket for UdpSocket { // net::UdpSocket::from_raw_socket(handle).into()
// unsafe fn from_raw_socket(handle: RawSocket) -> UdpSocket { // }
// net::UdpSocket::from_raw_socket(handle).into() // }
// } //
// } // impl IntoRawSocket for UdpSocket {
// // fn into_raw_socket(self) -> RawSocket {
// impl IntoRawSocket for UdpSocket { // self.raw_socket
// fn into_raw_socket(self) -> RawSocket { // }
// self.raw_socket // }
// }
// }
}
} }

View file

@ -1,9 +1,9 @@
//! OS-specific extensions. //! OS-specific extensions.
#[cfg(any(unix, feature = "docs"))] cfg_unix! {
#[cfg_attr(feature = "docs", doc(cfg(unix)))] pub mod unix;
pub mod unix; }
#[cfg(any(windows, feature = "docs"))] cfg_windows! {
#[cfg_attr(feature = "docs", doc(cfg(windows)))] pub mod windows;
pub mod windows; }

View file

@ -1,7 +1,5 @@
//! Unix-specific filesystem extensions. //! Unix-specific filesystem extensions.
use cfg_if::cfg_if;
use crate::io; use crate::io;
use crate::path::Path; use crate::path::Path;
use crate::task::blocking; use crate::task::blocking;
@ -31,43 +29,43 @@ pub async fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Resu
blocking::spawn(move || std::os::unix::fs::symlink(&src, &dst)).await blocking::spawn(move || std::os::unix::fs::symlink(&src, &dst)).await
} }
cfg_if! { cfg_not_docs! {
if #[cfg(feature = "docs")] { pub use std::os::unix::fs::{DirBuilderExt, DirEntryExt, OpenOptionsExt};
/// Unix-specific extensions to `DirBuilder`. }
pub trait DirBuilderExt {
/// Sets the mode to create new directories with. This option defaults to
/// `0o777`.
fn mode(&mut self, mode: u32) -> &mut Self;
}
/// Unix-specific extension methods for `DirEntry`. cfg_docs! {
pub trait DirEntryExt { /// Unix-specific extensions to `DirBuilder`.
/// Returns the underlying `d_ino` field in the contained `dirent` pub trait DirBuilderExt {
/// structure. /// Sets the mode to create new directories with. This option defaults to
fn ino(&self) -> u64; /// `0o777`.
} fn mode(&mut self, mode: u32) -> &mut Self;
}
/// Unix-specific extensions to `OpenOptions`. /// Unix-specific extension methods for `DirEntry`.
pub trait OpenOptionsExt { pub trait DirEntryExt {
/// Sets the mode bits that a new file will be created with. /// Returns the underlying `d_ino` field in the contained `dirent`
/// /// structure.
/// If a new file is created as part of a `File::open_opts` call then this fn ino(&self) -> u64;
/// specified `mode` will be used as the permission bits for the new file. }
/// If no `mode` is set, the default of `0o666` will be used.
/// The operating system masks out bits with the systems `umask`, to produce
/// the final permissions.
fn mode(&mut self, mode: u32) -> &mut Self;
/// Pass custom flags to the `flags` argument of `open`. /// Unix-specific extensions to `OpenOptions`.
/// pub trait OpenOptionsExt {
/// The bits that define the access mode are masked out with `O_ACCMODE`, to /// Sets the mode bits that a new file will be created with.
/// ensure they do not interfere with the access mode set by Rusts options. ///
/// /// If a new file is created as part of a `File::open_opts` call then this
/// Custom flags can only set flags, not remove flags set by Rusts options. /// specified `mode` will be used as the permission bits for the new file.
/// This options overwrites any previously set custom flags. /// If no `mode` is set, the default of `0o666` will be used.
fn custom_flags(&mut self, flags: i32) -> &mut Self; /// The operating system masks out bits with the systems `umask`, to produce
} /// the final permissions.
} else { fn mode(&mut self, mode: u32) -> &mut Self;
pub use std::os::unix::fs::{DirBuilderExt, OpenOptionsExt};
/// Pass custom flags to the `flags` argument of `open`.
///
/// The bits that define the access mode are masked out with `O_ACCMODE`, to
/// ensure they do not interfere with the access mode set by Rusts options.
///
/// Custom flags can only set flags, not remove flags set by Rusts options.
/// This options overwrites any previously set custom flags.
fn custom_flags(&mut self, flags: i32) -> &mut Self;
} }
} }

View file

@ -1,56 +1,54 @@
//! Unix-specific I/O extensions. //! Unix-specific I/O extensions.
use cfg_if::cfg_if; cfg_not_docs! {
pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
}
cfg_if! { cfg_docs! {
if #[cfg(feature = "docs")] { /// Raw file descriptors.
/// Raw file descriptors. pub type RawFd = std::os::raw::c_int;
pub type RawFd = std::os::raw::c_int;
/// A trait to extract the raw unix file descriptor from an underlying /// A trait to extract the raw unix file descriptor from an underlying
/// object. /// object.
///
/// This is only available on unix platforms and must be imported in order
/// to call the method. Windows platforms have a corresponding `AsRawHandle`
/// and `AsRawSocket` set of traits.
pub trait AsRawFd {
/// Extracts the raw file descriptor.
/// ///
/// This is only available on unix platforms and must be imported in order /// This method does **not** pass ownership of the raw file descriptor
/// to call the method. Windows platforms have a corresponding `AsRawHandle` /// to the caller. The descriptor is only guaranteed to be valid while
/// and `AsRawSocket` set of traits. /// the original object has not yet been destroyed.
pub trait AsRawFd { fn as_raw_fd(&self) -> RawFd;
/// Extracts the raw file descriptor. }
///
/// This method does **not** pass ownership of the raw file descriptor
/// to the caller. The descriptor is only guaranteed to be valid while
/// the original object has not yet been destroyed.
fn as_raw_fd(&self) -> RawFd;
}
/// A trait to express the ability to construct an object from a raw file /// A trait to express the ability to construct an object from a raw file
/// descriptor.
pub trait FromRawFd {
/// Constructs a new instance of `Self` from the given raw file
/// descriptor. /// descriptor.
pub trait FromRawFd { ///
/// Constructs a new instance of `Self` from the given raw file /// This function **consumes ownership** of the specified file
/// descriptor. /// descriptor. The returned object will take responsibility for closing
/// /// it when the object goes out of scope.
/// This function **consumes ownership** of the specified file ///
/// descriptor. The returned object will take responsibility for closing /// This function is also unsafe as the primitives currently returned
/// it when the object goes out of scope. /// have the contract that they are the sole owner of the file
/// /// descriptor they are wrapping. Usage of this function could
/// This function is also unsafe as the primitives currently returned /// accidentally allow violating this contract which can cause memory
/// have the contract that they are the sole owner of the file /// unsafety in code that relies on it being true.
/// descriptor they are wrapping. Usage of this function could unsafe fn from_raw_fd(fd: RawFd) -> Self;
/// accidentally allow violating this contract which can cause memory }
/// unsafety in code that relies on it being true.
unsafe fn from_raw_fd(fd: RawFd) -> Self;
}
/// A trait to express the ability to consume an object and acquire ownership of /// A trait to express the ability to consume an object and acquire ownership of
/// its raw file descriptor. /// its raw file descriptor.
pub trait IntoRawFd { pub trait IntoRawFd {
/// Consumes this object, returning the raw underlying file descriptor. /// Consumes this object, returning the raw underlying file descriptor.
/// ///
/// This function **transfers ownership** of the underlying file descriptor /// This function **transfers ownership** of the underlying file descriptor
/// to the caller. Callers are then the unique owners of the file descriptor /// to the caller. Callers are then the unique owners of the file descriptor
/// and must close the descriptor once it's no longer needed. /// and must close the descriptor once it's no longer needed.
fn into_raw_fd(self) -> RawFd; fn into_raw_fd(self) -> RawFd;
}
} else {
pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
} }
} }

View file

@ -1,7 +1,5 @@
//! Unix-specific networking extensions. //! Unix-specific networking extensions.
use cfg_if::cfg_if;
pub use datagram::UnixDatagram; pub use datagram::UnixDatagram;
pub use listener::{Incoming, UnixListener}; pub use listener::{Incoming, UnixListener};
pub use stream::UnixStream; pub use stream::UnixStream;
@ -10,90 +8,90 @@ mod datagram;
mod listener; mod listener;
mod stream; mod stream;
cfg_if! { cfg_not_docs! {
if #[cfg(feature = "docs")] { pub use std::os::unix::net::SocketAddr;
use std::fmt; }
use crate::path::Path; cfg_docs! {
use std::fmt;
/// An address associated with a Unix socket. use crate::path::Path;
/// An address associated with a Unix socket.
///
/// # Examples
///
/// ```
/// use async_std::os::unix::net::UnixListener;
///
/// let socket = UnixListener::bind("/tmp/socket").await?;
/// let addr = socket.local_addr()?;
/// ```
#[derive(Clone)]
pub struct SocketAddr {
_private: (),
}
impl SocketAddr {
/// Returns `true` if the address is unnamed.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// A named address:
///
/// ```no_run
/// use async_std::os::unix::net::UnixListener; /// use async_std::os::unix::net::UnixListener;
/// ///
/// let socket = UnixListener::bind("/tmp/socket").await?; /// let socket = UnixListener::bind("/tmp/socket").await?;
/// let addr = socket.local_addr()?; /// let addr = socket.local_addr()?;
/// assert_eq!(addr.is_unnamed(), false);
/// ``` /// ```
#[derive(Clone)] ///
pub struct SocketAddr { /// An unnamed address:
_private: (), ///
/// ```no_run
/// use async_std::os::unix::net::UnixDatagram;
///
/// let socket = UnixDatagram::unbound().await?;
/// let addr = socket.local_addr()?;
/// assert_eq!(addr.is_unnamed(), true);
/// ```
pub fn is_unnamed(&self) -> bool {
unreachable!("this impl only appears in the rendered docs")
} }
impl SocketAddr { /// Returns the contents of this address if it is a `pathname` address.
/// Returns `true` if the address is unnamed. ///
/// /// # Examples
/// # Examples ///
/// /// With a pathname:
/// A named address: ///
/// /// ```no_run
/// ```no_run /// use async_std::os::unix::net::UnixListener;
/// use async_std::os::unix::net::UnixListener; /// use async_std::path::Path;
/// ///
/// let socket = UnixListener::bind("/tmp/socket").await?; /// let socket = UnixListener::bind("/tmp/socket").await?;
/// let addr = socket.local_addr()?; /// let addr = socket.local_addr()?;
/// assert_eq!(addr.is_unnamed(), false); /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/socket")));
/// ``` /// ```
/// ///
/// An unnamed address: /// Without a pathname:
/// ///
/// ```no_run /// ```
/// use async_std::os::unix::net::UnixDatagram; /// use async_std::os::unix::net::UnixDatagram;
/// ///
/// let socket = UnixDatagram::unbound().await?; /// let socket = UnixDatagram::unbound()?;
/// let addr = socket.local_addr()?; /// let addr = socket.local_addr()?;
/// assert_eq!(addr.is_unnamed(), true); /// assert_eq!(addr.as_pathname(), None);
/// ``` /// ```
pub fn is_unnamed(&self) -> bool { pub fn as_pathname(&self) -> Option<&Path> {
unreachable!("this impl only appears in the rendered docs") unreachable!("this impl only appears in the rendered docs")
}
/// Returns the contents of this address if it is a `pathname` address.
///
/// # Examples
///
/// With a pathname:
///
/// ```no_run
/// use async_std::os::unix::net::UnixListener;
/// use async_std::path::Path;
///
/// let socket = UnixListener::bind("/tmp/socket").await?;
/// let addr = socket.local_addr()?;
/// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/socket")));
/// ```
///
/// Without a pathname:
///
/// ```
/// use async_std::os::unix::net::UnixDatagram;
///
/// let socket = UnixDatagram::unbound()?;
/// let addr = socket.local_addr()?;
/// assert_eq!(addr.as_pathname(), None);
/// ```
pub fn as_pathname(&self) -> Option<&Path> {
unreachable!("this impl only appears in the rendered docs")
}
} }
}
impl fmt::Debug for SocketAddr { impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
unreachable!("this impl only appears in the rendered docs") unreachable!("this impl only appears in the rendered docs")
}
} }
} else {
pub use std::os::unix::net::SocketAddr;
} }
} }

View file

@ -1,50 +1,48 @@
//! Windows-specific I/O extensions. //! Windows-specific I/O extensions.
use cfg_if::cfg_if; cfg_not_docs! {
pub use std::os::windows::io::{
AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle, RawSocket,
};
}
cfg_if! { cfg_docs! {
if #[cfg(feature = "docs")] { /// Raw HANDLEs.
/// Raw HANDLEs. pub type RawHandle = *mut std::os::raw::c_void;
pub type RawHandle = *mut std::os::raw::c_void;
/// Raw SOCKETs. /// Raw SOCKETs.
pub type RawSocket = u64; pub type RawSocket = u64;
/// Extracts raw handles. /// Extracts raw handles.
pub trait AsRawHandle { pub trait AsRawHandle {
/// Extracts the raw handle, without taking any ownership. /// Extracts the raw handle, without taking any ownership.
fn as_raw_handle(&self) -> RawHandle; fn as_raw_handle(&self) -> RawHandle;
} }
/// Construct I/O objects from raw handles. /// Construct I/O objects from raw handles.
pub trait FromRawHandle { pub trait FromRawHandle {
/// Constructs a new I/O object from the specified raw handle. /// Constructs a new I/O object from the specified raw handle.
/// ///
/// This function will **consume ownership** of the handle given, /// This function will **consume ownership** of the handle given,
/// passing responsibility for closing the handle to the returned /// passing responsibility for closing the handle to the returned
/// object. /// object.
/// ///
/// This function is also unsafe as the primitives currently returned /// This function is also unsafe as the primitives currently returned
/// have the contract that they are the sole owner of the file /// have the contract that they are the sole owner of the file
/// descriptor they are wrapping. Usage of this function could /// descriptor they are wrapping. Usage of this function could
/// accidentally allow violating this contract which can cause memory /// accidentally allow violating this contract which can cause memory
/// unsafety in code that relies on it being true. /// unsafety in code that relies on it being true.
unsafe fn from_raw_handle(handle: RawHandle) -> Self; unsafe fn from_raw_handle(handle: RawHandle) -> Self;
} }
/// A trait to express the ability to consume an object and acquire ownership of /// A trait to express the ability to consume an object and acquire ownership of
/// its raw `HANDLE`. /// its raw `HANDLE`.
pub trait IntoRawHandle { pub trait IntoRawHandle {
/// Consumes this object, returning the raw underlying handle. /// Consumes this object, returning the raw underlying handle.
/// ///
/// This function **transfers ownership** of the underlying handle to the /// This function **transfers ownership** of the underlying handle to the
/// caller. Callers are then the unique owners of the handle and must close /// caller. Callers are then the unique owners of the handle and must close
/// it once it's no longer needed. /// it once it's no longer needed.
fn into_raw_handle(self) -> RawHandle; fn into_raw_handle(self) -> RawHandle;
}
} else {
pub use std::os::windows::io::{
AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle, RawSocket,
};
} }
} }

View file

@ -11,8 +11,6 @@
//! use async_std::prelude::*; //! use async_std::prelude::*;
//! ``` //! ```
use cfg_if::cfg_if;
#[doc(no_inline)] #[doc(no_inline)]
pub use crate::future::Future; pub use crate::future::Future;
#[doc(no_inline)] #[doc(no_inline)]
@ -41,12 +39,9 @@ pub use crate::io::write::WriteExt as _;
#[doc(hidden)] #[doc(hidden)]
pub use crate::stream::stream::StreamExt as _; pub use crate::stream::stream::StreamExt as _;
cfg_if! { cfg_unstable! {
if #[cfg(any(feature = "unstable", feature = "docs"))] { #[doc(no_inline)]
#[doc(no_inline)] pub use crate::stream::DoubleEndedStream;
pub use crate::stream::DoubleEndedStream; #[doc(no_inline)]
pub use crate::stream::ExactSizeStream;
#[doc(no_inline)]
pub use crate::stream::ExactSizeStream;
}
} }

View file

@ -10,8 +10,8 @@ use std::task::{Context, Poll};
/// `Item`s from the back, as well as the front. /// `Item`s from the back, as well as the front.
/// ///
/// [`Stream`]: trait.Stream.html /// [`Stream`]: trait.Stream.html
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[cfg(any(feature = "unstable", feature = "docs"))]
pub trait DoubleEndedStream: Stream { pub trait DoubleEndedStream: Stream {
/// Removes and returns an element from the end of the stream. /// Removes and returns an element from the end of the stream.
/// ///

View file

@ -76,8 +76,8 @@ pub use crate::stream::Stream;
/// # }); /// # });
/// # } /// # }
/// ``` /// ```
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[cfg(any(feature = "unstable", feature = "docs"))]
pub trait ExactSizeStream: Stream { pub trait ExactSizeStream: Stream {
/// Returns the exact number of times the stream will iterate. /// Returns the exact number of times the stream will iterate.
/// ///

View file

@ -27,6 +27,7 @@ use crate::stream::IntoStream;
/// # /// #
/// # }) } /// # }) }
/// ``` /// ```
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
pub trait Extend<A> { pub trait Extend<A> {
/// Extends a collection with the contents of a stream. /// Extends a collection with the contents of a stream.

View file

@ -106,8 +106,8 @@ use std::pin::Pin;
///``` ///```
/// ///
/// [`IntoStream`]: trait.IntoStream.html /// [`IntoStream`]: trait.IntoStream.html
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[cfg(any(feature = "unstable", feature = "docs"))]
pub trait FromStream<T> { pub trait FromStream<T> {
/// Creates a value from a stream. /// Creates a value from a stream.
/// ///

View file

@ -14,7 +14,7 @@ use crate::stream::Stream;
/// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None
/// [`Stream::fuse`]: trait.Stream.html#method.fuse /// [`Stream::fuse`]: trait.Stream.html#method.fuse
/// [`Fuse`]: struct.Fuse.html /// [`Fuse`]: struct.Fuse.html
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
pub trait FusedStream: Stream {} pub trait FusedStream: Stream {}

View file

@ -43,9 +43,8 @@ use futures_timer::Delay;
/// # /// #
/// # Ok(()) }) } /// # Ok(()) }) }
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[doc(inline)]
pub fn interval(dur: Duration) -> Interval { pub fn interval(dur: Duration) -> Interval {
Interval { Interval {
delay: Delay::new(dur), delay: Delay::new(dur),
@ -55,9 +54,9 @@ pub fn interval(dur: Duration) -> Interval {
/// A stream representing notifications at fixed interval /// A stream representing notifications at fixed interval
/// ///
#[derive(Debug)] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[doc(inline)] #[derive(Debug)]
pub struct Interval { pub struct Interval {
delay: Delay, delay: Delay,
interval: Duration, interval: Duration,

View file

@ -13,8 +13,8 @@ use crate::stream::Stream;
/// See also: [`FromStream`]. /// See also: [`FromStream`].
/// ///
/// [`FromStream`]: trait.FromStream.html /// [`FromStream`]: trait.FromStream.html
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[cfg(any(feature = "unstable", feature = "docs"))]
pub trait IntoStream { pub trait IntoStream {
/// The type of the elements being iterated over. /// The type of the elements being iterated over.
type Item; type Item;

View file

@ -21,8 +21,6 @@
//! # }) //! # })
//! ``` //! ```
use cfg_if::cfg_if;
pub use empty::{empty, Empty}; pub use empty::{empty, Empty};
pub use from_fn::{from_fn, FromFn}; pub use from_fn::{from_fn, FromFn};
pub use once::{once, Once}; pub use once::{once, Once};
@ -40,28 +38,25 @@ mod once;
mod repeat; mod repeat;
mod repeat_with; mod repeat_with;
cfg_if! { cfg_unstable! {
if #[cfg(any(feature = "unstable", feature = "docs"))] { mod double_ended_stream;
mod double_ended_stream; mod exact_size_stream;
mod exact_size_stream; mod extend;
mod extend; mod from_stream;
mod from_stream; mod fused_stream;
mod fused_stream; mod interval;
mod interval; mod into_stream;
mod into_stream; mod product;
mod product; mod sum;
mod sum;
pub use double_ended_stream::DoubleEndedStream; pub use double_ended_stream::DoubleEndedStream;
pub use exact_size_stream::ExactSizeStream; pub use exact_size_stream::ExactSizeStream;
pub use extend::Extend; pub use extend::Extend;
pub use from_stream::FromStream; pub use from_stream::FromStream;
pub use fused_stream::FusedStream; pub use fused_stream::FusedStream;
pub use interval::{interval, Interval}; pub use interval::{interval, Interval};
pub use into_stream::IntoStream; pub use into_stream::IntoStream;
pub use product::Product; pub use product::Product;
pub use sum::Sum; pub use stream::Merge;
pub use sum::Sum;
pub use stream::Merge;
}
} }

View file

@ -11,8 +11,8 @@ use crate::stream::Stream;
/// [`product`]: trait.Product.html#tymethod.product /// [`product`]: trait.Product.html#tymethod.product
/// [`FromStream`]: trait.FromStream.html /// [`FromStream`]: trait.FromStream.html
/// [`Stream::product`]: trait.Stream.html#method.product /// [`Stream::product`]: trait.Stream.html#method.product
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[cfg(any(feature = "unstable", feature = "docs"))]
pub trait Product<A = Self>: Sized { pub trait Product<A = Self>: Sized {
/// Method which takes a stream and generates `Self` from the elements by /// Method which takes a stream and generates `Self` from the elements by
/// multiplying the items. /// multiplying the items.

View file

@ -8,7 +8,7 @@ use futures_core::Stream;
/// This stream is returned by [`Stream::merge`]. /// This stream is returned by [`Stream::merge`].
/// ///
/// [`Stream::merge`]: trait.Stream.html#method.merge /// [`Stream::merge`]: trait.Stream.html#method.merge
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[derive(Debug)] #[derive(Debug)]
pub struct Merge<L, R> { pub struct Merge<L, R> {

View file

@ -94,32 +94,22 @@ use std::cmp::Ordering;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::time::Duration; use std::time::Duration;
use cfg_if::cfg_if; cfg_unstable! {
use std::pin::Pin;
use crate::utils::extension_trait; use crate::future::Future;
use crate::stream::FromStream;
cfg_if! { pub use merge::Merge;
if #[cfg(feature = "docs")] {
use std::ops::{Deref, DerefMut};
use crate::task::{Context, Poll}; mod merge;
}
}
cfg_if! {
if #[cfg(any(feature = "unstable", feature = "docs"))] {
mod merge;
use std::pin::Pin;
use crate::future::Future;
use crate::stream::FromStream;
pub use merge::Merge;
}
} }
extension_trait! { extension_trait! {
use std::ops::{Deref, DerefMut};
use crate::task::{Context, Poll};
#[doc = r#" #[doc = r#"
An asynchronous stream of values. An asynchronous stream of values.
@ -1286,7 +1276,7 @@ extension_trait! {
[`stream`]: trait.Stream.html#tymethod.next [`stream`]: trait.Stream.html#tymethod.next
"#] "#]
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"]
fn collect<'a, B>( fn collect<'a, B>(
@ -1325,7 +1315,7 @@ extension_trait! {
# }); # });
``` ```
"#] "#]
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
fn merge<U>(self, other: U) -> Merge<Self, U> fn merge<U>(self, other: U) -> Merge<Self, U>
where where

View file

@ -11,8 +11,8 @@ use crate::stream::Stream;
/// [`sum`]: trait.Sum.html#tymethod.sum /// [`sum`]: trait.Sum.html#tymethod.sum
/// [`FromStream`]: trait.FromStream.html /// [`FromStream`]: trait.FromStream.html
/// [`Stream::sum`]: trait.Stream.html#method.sum /// [`Stream::sum`]: trait.Stream.html#method.sum
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[cfg(any(feature = "unstable", feature = "docs"))]
pub trait Sum<A = Self>: Sized { pub trait Sum<A = Self>: Sized {
/// Method which takes a stream and generates `Self` from the elements by /// Method which takes a stream and generates `Self` from the elements by
/// "summing up" the items. /// "summing up" the items.

View file

@ -32,6 +32,7 @@ use crate::sync::Mutex;
/// # }); /// # });
/// # } /// # }
/// ``` /// ```
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[derive(Debug)] #[derive(Debug)]
pub struct Barrier { pub struct Barrier {
@ -61,6 +62,7 @@ struct BarrierState {
/// let barrier = Barrier::new(1); /// let barrier = Barrier::new(1);
/// let barrier_wait_result = barrier.wait(); /// let barrier_wait_result = barrier.wait();
/// ``` /// ```
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct BarrierWaitResult(bool); pub struct BarrierWaitResult(bool);

View file

@ -32,14 +32,13 @@
#[doc(inline)] #[doc(inline)]
pub use std::sync::{Arc, Weak}; pub use std::sync::{Arc, Weak};
#[cfg(any(feature = "unstable", feature = "docs"))]
pub use barrier::{Barrier, BarrierWaitResult};
pub use mutex::{Mutex, MutexGuard}; pub use mutex::{Mutex, MutexGuard};
pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard};
#[cfg(any(feature = "unstable", feature = "docs"))]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
mod barrier;
mod mutex; mod mutex;
mod rwlock; mod rwlock;
cfg_unstable! {
pub use barrier::{Barrier, BarrierWaitResult};
mod barrier;
}

View file

@ -1,10 +1,12 @@
use std::cell::UnsafeCell; use std::cell::{Cell, UnsafeCell};
use std::mem::{self, ManuallyDrop}; use std::mem::{self, ManuallyDrop};
use std::panic::{self, AssertUnwindSafe, UnwindSafe}; use std::panic::{self, AssertUnwindSafe, UnwindSafe};
use std::pin::Pin; use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use std::task::{RawWaker, RawWakerVTable}; use std::task::{RawWaker, RawWakerVTable};
use std::thread::{self, Thread}; use std::thread;
use crossbeam_utils::sync::Parker;
use super::task; use super::task;
use super::task_local; use super::task_local;
@ -119,13 +121,21 @@ where
F: Future<Output = T>, F: Future<Output = T>,
{ {
thread_local! { thread_local! {
static ARC_THREAD: Arc<Thread> = Arc::new(thread::current()); // May hold a pre-allocated parker that can be reused for efficiency.
//
// Note that each invocation of `block` needs its own parker. In particular, if `block`
// recursively calls itself, we must make sure that each recursive call uses a distinct
// parker instance.
static CACHE: Cell<Option<Arc<Parker>>> = Cell::new(None);
} }
pin_utils::pin_mut!(f); pin_utils::pin_mut!(f);
ARC_THREAD.with(|arc_thread: &Arc<Thread>| { CACHE.with(|cache| {
let ptr = (&**arc_thread as *const Thread) as *const (); // Reuse a cached parker or create a new one for this invocation of `block`.
let arc_parker: Arc<Parker> = cache.take().unwrap_or_else(|| Arc::new(Parker::new()));
let ptr = (&*arc_parker as *const Parker) as *const ();
let vt = vtable(); let vt = vtable();
let waker = unsafe { ManuallyDrop::new(Waker::from_raw(RawWaker::new(ptr, vt))) }; let waker = unsafe { ManuallyDrop::new(Waker::from_raw(RawWaker::new(ptr, vt))) };
@ -133,32 +143,34 @@ where
loop { loop {
if let Poll::Ready(t) = f.as_mut().poll(cx) { if let Poll::Ready(t) = f.as_mut().poll(cx) {
// Save the parker for the next invocation of `block`.
cache.set(Some(arc_parker));
return t; return t;
} }
thread::park(); arc_parker.park();
} }
}) })
} }
fn vtable() -> &'static RawWakerVTable { fn vtable() -> &'static RawWakerVTable {
unsafe fn clone_raw(ptr: *const ()) -> RawWaker { unsafe fn clone_raw(ptr: *const ()) -> RawWaker {
let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Thread)); let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Parker));
mem::forget(arc.clone()); mem::forget(arc.clone());
RawWaker::new(ptr, vtable()) RawWaker::new(ptr, vtable())
} }
unsafe fn wake_raw(ptr: *const ()) { unsafe fn wake_raw(ptr: *const ()) {
let arc = Arc::from_raw(ptr as *const Thread); let arc = Arc::from_raw(ptr as *const Parker);
arc.unpark(); arc.unparker().unpark();
} }
unsafe fn wake_by_ref_raw(ptr: *const ()) { unsafe fn wake_by_ref_raw(ptr: *const ()) {
let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Thread)); let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Parker));
arc.unpark(); arc.unparker().unpark();
} }
unsafe fn drop_raw(ptr: *const ()) { unsafe fn drop_raw(ptr: *const ()) {
drop(Arc::from_raw(ptr as *const Thread)) drop(Arc::from_raw(ptr as *const Parker))
} }
&RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw) &RawWakerVTable::new(clone_raw, wake_raw, wake_by_ref_raw, drop_raw)

View file

@ -143,11 +143,9 @@ mod worker;
pub(crate) mod blocking; pub(crate) mod blocking;
cfg_if::cfg_if! { cfg_unstable! {
if #[cfg(any(feature = "unstable", feature = "docs"))] { mod yield_now;
mod yield_now; pub use yield_now::yield_now;
pub use yield_now::yield_now;
}
} }
/// Spawns a blocking task. /// Spawns a blocking task.
@ -178,7 +176,7 @@ cfg_if::cfg_if! {
/// ``` /// ```
// Once this function stabilizes we should merge `blocking::spawn` into this so // Once this function stabilizes we should merge `blocking::spawn` into this so
// all code in our crate uses `task::blocking` too. // all code in our crate uses `task::blocking` too.
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[inline] #[inline]
pub fn spawn_blocking<F, R>(f: F) -> task::JoinHandle<R> pub fn spawn_blocking<F, R>(f: F) -> task::JoinHandle<R>

View file

@ -26,7 +26,7 @@ use std::pin::Pin;
/// # /// #
/// # }) } /// # }) }
/// ``` /// ```
#[cfg(any(feature = "unstable", feature = "docs"))] #[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[cfg_attr(feature = "docs", doc(cfg(unstable)))]
#[inline] #[inline]
pub async fn yield_now() { pub async fn yield_now() {

View file

@ -20,6 +20,64 @@ pub fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
t t
} }
/// Declares unstable items.
#[doc(hidden)]
macro_rules! cfg_unstable {
($($item:item)*) => {
$(
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
$item
)*
}
}
/// Declares Unix-specific items.
#[doc(hidden)]
macro_rules! cfg_unix {
($($item:item)*) => {
$(
#[cfg(any(unix, feature = "docs"))]
#[cfg_attr(feature = "docs", doc(cfg(unix)))]
$item
)*
}
}
/// Declares Windows-specific items.
#[doc(hidden)]
macro_rules! cfg_windows {
($($item:item)*) => {
$(
#[cfg(any(windows, feature = "docs"))]
#[cfg_attr(feature = "docs", doc(cfg(windows)))]
$item
)*
}
}
/// Declares items when the "docs" feature is enabled.
#[doc(hidden)]
macro_rules! cfg_docs {
($($item:item)*) => {
$(
#[cfg(feature = "docs")]
$item
)*
}
}
/// Declares items when the "docs" feature is disabled.
#[doc(hidden)]
macro_rules! cfg_not_docs {
($($item:item)*) => {
$(
#[cfg(not(feature = "docs"))]
$item
)*
}
}
/// Defines an extension trait for a base trait. /// Defines an extension trait for a base trait.
/// ///
/// In generated docs, the base trait will contain methods from the extension trait. In actual /// In generated docs, the base trait will contain methods from the extension trait. In actual
@ -29,7 +87,6 @@ pub fn abort_on_panic<T>(f: impl FnOnce() -> T) -> T {
/// Inside invocations of this macro, we write a definitions that looks similar to the final /// Inside invocations of this macro, we write a definitions that looks similar to the final
/// rendered docs, and the macro then generates all the boilerplate for us. /// rendered docs, and the macro then generates all the boilerplate for us.
#[doc(hidden)] #[doc(hidden)]
#[macro_export]
macro_rules! extension_trait { macro_rules! extension_trait {
( (
// Interesting patterns: // Interesting patterns:
@ -113,6 +170,12 @@ macro_rules! extension_trait {
// Handle the end of the token list. // Handle the end of the token list.
(@doc ($($head:tt)*)) => { $($head)* }; (@doc ($($head:tt)*)) => { $($head)* };
(@ext ($($head:tt)*)) => { $($head)* }; (@ext ($($head:tt)*)) => { $($head)* };
}
pub use crate::extension_trait; // Parse imports at the beginning of the macro.
($import:item $($tail:tt)*) => {
#[cfg(feature = "docs")]
$import
extension_trait!($($tail)*);
};
}

View file

@ -48,13 +48,13 @@ fn test_buffered_writer() {
} }
#[test] #[test]
fn test_buffered_writer_inner_into_inner_does_not_flush() { fn test_buffered_writer_inner_into_inner_flushes() {
task::block_on(async { task::block_on(async {
let mut w = BufWriter::with_capacity(3, Vec::new()); let mut w = BufWriter::with_capacity(3, Vec::new());
w.write(&[0, 1]).await.unwrap(); w.write(&[0, 1]).await.unwrap();
assert_eq!(*w.get_ref(), []); assert_eq!(*w.get_ref(), []);
let w = w.into_inner().await.unwrap(); let w = w.into_inner().await.unwrap();
assert_eq!(w, []); assert_eq!(w, [0, 1]);
}) })
} }