From e405544ea0b6cac9fd599ab6f86383db261ff601 Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 17 Oct 2019 07:06:29 +0900 Subject: [PATCH 1/3] Enable tests on CI (#357) * Enable tests on CI * Fix failed test --- .github/workflows/ci.yml | 2 +- tests/buf_writer.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b92e50b..c622a59 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all --doc --features unstable + args: --all --features unstable check_fmt_and_docs: name: Checking fmt and docs diff --git a/tests/buf_writer.rs b/tests/buf_writer.rs index fa0e1ed..cb2368a 100644 --- a/tests/buf_writer.rs +++ b/tests/buf_writer.rs @@ -48,13 +48,13 @@ fn test_buffered_writer() { } #[test] -fn test_buffered_writer_inner_into_inner_does_not_flush() { +fn test_buffered_writer_inner_into_inner_flushes() { task::block_on(async { let mut w = BufWriter::with_capacity(3, Vec::new()); w.write(&[0, 1]).await.unwrap(); assert_eq!(*w.get_ref(), []); let w = w.into_inner().await.unwrap(); - assert_eq!(w, []); + assert_eq!(w, [0, 1]); }) } From 46f0fb1c6407a5417eeedfedfed5fdf5a5e9cef6 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 17 Oct 2019 11:52:42 +0200 Subject: [PATCH 2/3] Make sure each invocation of block_on uses its own Parker (#358) --- Cargo.toml | 1 + src/task/block_on.rs | 36 ++++++++++++++++++++++++------------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d1c10a6..e8e2ccc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ async-task = "1.0.0" cfg-if = "0.1.9" crossbeam-channel = "0.3.9" crossbeam-deque = "0.7.1" +crossbeam-utils = "0.6.6" futures-core-preview = "=0.3.0-alpha.19" futures-io-preview = "=0.3.0-alpha.19" futures-timer = "1.0.2" diff --git a/src/task/block_on.rs b/src/task/block_on.rs index db46f02..032bf02 100644 --- a/src/task/block_on.rs +++ b/src/task/block_on.rs @@ -1,10 +1,12 @@ -use std::cell::UnsafeCell; +use std::cell::{Cell, UnsafeCell}; use std::mem::{self, ManuallyDrop}; use std::panic::{self, AssertUnwindSafe, UnwindSafe}; use std::pin::Pin; use std::sync::Arc; use std::task::{RawWaker, RawWakerVTable}; -use std::thread::{self, Thread}; +use std::thread; + +use crossbeam_utils::sync::Parker; use super::task; use super::task_local; @@ -119,13 +121,21 @@ where F: Future, { thread_local! { - static ARC_THREAD: Arc = 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>> = Cell::new(None); } pin_utils::pin_mut!(f); - ARC_THREAD.with(|arc_thread: &Arc| { - let ptr = (&**arc_thread as *const Thread) as *const (); + CACHE.with(|cache| { + // Reuse a cached parker or create a new one for this invocation of `block`. + let arc_parker: Arc = cache.take().unwrap_or_else(|| Arc::new(Parker::new())); + + let ptr = (&*arc_parker as *const Parker) as *const (); let vt = vtable(); let waker = unsafe { ManuallyDrop::new(Waker::from_raw(RawWaker::new(ptr, vt))) }; @@ -133,32 +143,34 @@ where loop { 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; } - thread::park(); + arc_parker.park(); } }) } fn vtable() -> &'static RawWakerVTable { 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()); RawWaker::new(ptr, vtable()) } unsafe fn wake_raw(ptr: *const ()) { - let arc = Arc::from_raw(ptr as *const Thread); - arc.unpark(); + let arc = Arc::from_raw(ptr as *const Parker); + arc.unparker().unpark(); } unsafe fn wake_by_ref_raw(ptr: *const ()) { - let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Thread)); - arc.unpark(); + let arc = ManuallyDrop::new(Arc::from_raw(ptr as *const Parker)); + arc.unparker().unpark(); } 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) From ec23632f3e7d2d8f9ed49995b85741eeb0a5be69 Mon Sep 17 00:00:00 2001 From: Stjepan Glavina Date: Thu, 17 Oct 2019 19:17:49 +0200 Subject: [PATCH 3/3] Cleanup: replace cfg-if with our macros (#361) * Cleanup: replace cfg-if with our macros * Prefix macros with cfg_ * Remove #[macro_export] from internal macros --- Cargo.toml | 3 +- src/fs/dir_builder.rs | 23 +- src/fs/dir_entry.rs | 21 +- src/fs/file.rs | 85 +++----- src/fs/file_type.rs | 148 +++++++------ src/fs/metadata.rs | 350 +++++++++++++++--------------- src/fs/open_options.rs | 31 +-- src/fs/permissions.rs | 98 ++++----- src/future/future.rs | 14 +- src/future/into_future.rs | 2 +- src/future/mod.rs | 16 +- src/io/buf_read/mod.rs | 11 +- src/io/read/mod.rs | 66 +++--- src/io/{seek.rs => seek/mod.rs} | 37 +--- src/io/seek/seek.rs | 21 ++ src/io/stderr.rs | 37 +--- src/io/stdin.rs | 37 +--- src/io/stdout.rs | 37 +--- src/io/write/mod.rs | 18 +- src/lib.rs | 34 ++- src/macros.rs | 8 +- src/net/addr.rs | 24 +- src/net/tcp/listener.rs | 84 +++---- src/net/tcp/stream.rs | 81 +++---- src/net/udp/mod.rs | 83 +++---- src/os/mod.rs | 12 +- src/os/unix/fs.rs | 72 +++--- src/os/unix/io.rs | 90 ++++---- src/os/unix/net/mod.rs | 142 ++++++------ src/os/windows/io.rs | 80 ++++--- src/{pin.rs => pin/mod.rs} | 0 src/prelude.rs | 15 +- src/stream/double_ended_stream.rs | 2 +- src/stream/exact_size_stream.rs | 2 +- src/stream/extend.rs | 1 + src/stream/from_stream.rs | 2 +- src/stream/fused_stream.rs | 2 +- src/stream/interval.rs | 7 +- src/stream/into_stream.rs | 2 +- src/stream/mod.rs | 45 ++-- src/stream/product.rs | 2 +- src/stream/stream/merge.rs | 2 +- src/stream/stream/mod.rs | 44 ++-- src/stream/sum.rs | 2 +- src/sync/barrier.rs | 2 + src/sync/mod.rs | 11 +- src/task/mod.rs | 10 +- src/task/yield_now.rs | 2 +- src/utils.rs | 69 +++++- 49 files changed, 917 insertions(+), 1070 deletions(-) rename src/io/{seek.rs => seek/mod.rs} (80%) create mode 100644 src/io/seek/seek.rs rename src/{pin.rs => pin/mod.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index e8e2ccc..2741a19 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,13 +21,12 @@ features = ["docs"] rustdoc-args = ["--cfg", "feature=\"docs\""] [features] -docs = ["broadcaster"] +docs = ["unstable"] unstable = ["broadcaster"] [dependencies] async-macros = "1.0.0" async-task = "1.0.0" -cfg-if = "0.1.9" crossbeam-channel = "0.3.9" crossbeam-deque = "0.7.1" crossbeam-utils = "0.6.6" diff --git a/src/fs/dir_builder.rs b/src/fs/dir_builder.rs index 6dfddcb..a55a9a9 100644 --- a/src/fs/dir_builder.rs +++ b/src/fs/dir_builder.rs @@ -1,7 +1,5 @@ use std::future::Future; -use cfg_if::cfg_if; - use crate::io; use crate::path::Path; use crate::task::blocking; @@ -113,22 +111,13 @@ impl DirBuilder { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::fs::DirBuilderExt; - } else if #[cfg(unix)] { - use std::os::unix::fs::DirBuilderExt; - } -} +cfg_unix! { + use crate::os::unix::fs::DirBuilderExt; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl DirBuilderExt for DirBuilder { - fn mode(&mut self, mode: u32) -> &mut Self { - self.mode = Some(mode); - self - } + impl DirBuilderExt for DirBuilder { + fn mode(&mut self, mode: u32) -> &mut Self { + self.mode = Some(mode); + self } } } diff --git a/src/fs/dir_entry.rs b/src/fs/dir_entry.rs index 80d4bbd..959e2ad 100644 --- a/src/fs/dir_entry.rs +++ b/src/fs/dir_entry.rs @@ -2,8 +2,6 @@ use std::ffi::OsString; use std::fmt; use std::sync::Arc; -use cfg_if::cfg_if; - use crate::fs::{FileType, Metadata}; use crate::io; use crate::path::PathBuf; @@ -160,21 +158,12 @@ impl fmt::Debug for DirEntry { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::fs::DirEntryExt; - } else if #[cfg(unix)] { - use std::os::unix::fs::DirEntryExt; - } -} +cfg_unix! { + use crate::os::unix::fs::DirEntryExt; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl DirEntryExt for DirEntry { - fn ino(&self) -> u64 { - self.0.ino() - } + impl DirEntryExt for DirEntry { + fn ino(&self) -> u64 { + self.0.ino() } } } diff --git a/src/fs/file.rs b/src/fs/file.rs index 3916234..3129e96 100644 --- a/src/fs/file.rs +++ b/src/fs/file.rs @@ -7,8 +7,6 @@ use std::pin::Pin; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -use cfg_if::cfg_if; - use crate::fs::{Metadata, Permissions}; use crate::future; use crate::io::{self, Read, Seek, SeekFrom, Write}; @@ -401,67 +399,54 @@ impl From for File { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } else if #[cfg(unix)] { - use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - } else if #[cfg(windows)] { - use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } -} +cfg_unix! { + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for File { - fn as_raw_fd(&self) -> RawFd { - self.file.as_raw_fd() - } + impl AsRawFd for File { + fn as_raw_fd(&self) -> RawFd { + self.file.as_raw_fd() } + } - impl FromRawFd for File { - unsafe fn from_raw_fd(fd: RawFd) -> File { - std::fs::File::from_raw_fd(fd).into() - } + impl FromRawFd for File { + unsafe fn from_raw_fd(fd: RawFd) -> File { + std::fs::File::from_raw_fd(fd).into() } + } - impl IntoRawFd for File { - 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() - } + impl IntoRawFd for File { + 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_if! { - if #[cfg(any(windows, feature = "docs"))] { - impl AsRawHandle for File { - fn as_raw_handle(&self) -> RawHandle { - self.file.as_raw_handle() - } +cfg_windows! { + use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; + + impl AsRawHandle for File { + fn as_raw_handle(&self) -> RawHandle { + self.file.as_raw_handle() } + } - impl FromRawHandle for File { - unsafe fn from_raw_handle(handle: RawHandle) -> File { - std::fs::File::from_raw_handle(handle).into() - } + impl FromRawHandle for File { + unsafe fn from_raw_handle(handle: RawHandle) -> File { + std::fs::File::from_raw_handle(handle).into() } + } - 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() - } + 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() } } } diff --git a/src/fs/file_type.rs b/src/fs/file_type.rs index a162798..11f47d1 100644 --- a/src/fs/file_type.rs +++ b/src/fs/file_type.rs @@ -1,86 +1,84 @@ -use cfg_if::cfg_if; +cfg_not_docs! { + pub use std::fs::FileType; +} + +cfg_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: (), + } -cfg_if! { - if #[cfg(feature = "docs")] { - /// The type of a file or directory. + 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`], - /// [`is_file`], and [`is_symlink`] can return `true`. + /// # Examples /// - /// 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 - /// [`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: (), + /// let file_type = fs::metadata(".").await?.file_type(); + /// println!("{:?}", file_type.is_dir()); + /// # + /// # Ok(()) }) } + /// ``` + pub fn is_dir(&self) -> bool { + unimplemented!() } - 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 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!() - } + /// 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; } } diff --git a/src/fs/metadata.rs b/src/fs/metadata.rs index 65f494b..4afc559 100644 --- a/src/fs/metadata.rs +++ b/src/fs/metadata.rs @@ -1,5 +1,3 @@ -use cfg_if::cfg_if; - use crate::io; use crate::path::Path; use crate::task::blocking; @@ -39,193 +37,193 @@ pub async fn metadata>(path: P) -> io::Result { blocking::spawn(move || std::fs::metadata(path)).await } -cfg_if! { - if #[cfg(feature = "docs")] { - use std::time::SystemTime; +cfg_not_docs! { + pub use std::fs::Metadata; +} + +cfg_docs! { + use std::time::SystemTime; - use crate::fs::{FileType, Permissions}; + use crate::fs::{FileType, Permissions}; - /// Metadata for a file or directory. + /// 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 - /// [`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: (), + /// let metadata = fs::metadata("a.txt").await?; + /// println!("{:?}", metadata.file_type()); + /// # + /// # Ok(()) }) } + /// ``` + pub fn file_type(&self) -> FileType { + unimplemented!() } - impl Metadata { - /// Returns the file type from this metadata. - /// - /// # 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.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 async_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 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 async_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 async_std::fs; - /// - /// let metadata = fs::metadata("a.txt").await?; - /// println!("{:?}", metadata.is_file()); - /// # - /// # Ok(()) }) } - /// ``` - pub fn is_file(&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 async_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 async_std::fs; - /// - /// let metadata = fs::metadata("a.txt").await?; - /// println!("{}", metadata.len()); - /// # - /// # Ok(()) }) } - /// ``` - pub fn len(&self) -> u64 { - unimplemented!() - } + /// Returns the file size in bytes. + /// + /// # 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.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 async_std::fs; - /// - /// let metadata = fs::metadata("a.txt").await?; - /// println!("{:?}", metadata.permissions()); - /// # - /// # Ok(()) }) } - /// ``` - pub fn permissions(&self) -> Permissions { - unimplemented!() - } + /// Returns the permissions from this metadata. + /// + /// # 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.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 async_std::fs; - /// - /// let metadata = fs::metadata("a.txt").await?; - /// println!("{:?}", metadata.modified()); - /// # - /// # Ok(()) }) } - /// ``` - pub fn modified(&self) -> io::Result { - 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 async_std::fs; + /// + /// let metadata = fs::metadata("a.txt").await?; + /// println!("{:?}", metadata.modified()); + /// # + /// # Ok(()) }) } + /// ``` + pub fn modified(&self) -> io::Result { + 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 async_std::fs; - /// - /// let metadata = fs::metadata("a.txt").await?; - /// println!("{:?}", metadata.accessed()); - /// # - /// # Ok(()) }) } - /// ``` - pub fn accessed(&self) -> io::Result { - 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 async_std::fs; + /// + /// let metadata = fs::metadata("a.txt").await?; + /// println!("{:?}", metadata.accessed()); + /// # + /// # Ok(()) }) } + /// ``` + pub fn accessed(&self) -> io::Result { + 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 async_std::fs; - /// - /// let metadata = fs::metadata("a.txt").await?; - /// println!("{:?}", metadata.created()); - /// # - /// # Ok(()) }) } - /// ``` - pub fn created(&self) -> io::Result { - 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 async_std::fs; + /// + /// let metadata = fs::metadata("a.txt").await?; + /// println!("{:?}", metadata.created()); + /// # + /// # Ok(()) }) } + /// ``` + pub fn created(&self) -> io::Result { + unimplemented!() } - } else { - pub use std::fs::Metadata; } } diff --git a/src/fs/open_options.rs b/src/fs/open_options.rs index fe65e2f..a2eb9e7 100644 --- a/src/fs/open_options.rs +++ b/src/fs/open_options.rs @@ -1,7 +1,5 @@ use std::future::Future; -use cfg_if::cfg_if; - use crate::fs::File; use crate::io; use crate::path::Path; @@ -296,27 +294,18 @@ impl Default for OpenOptions { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::fs::OpenOptionsExt; - } else if #[cfg(unix)] { - use std::os::unix::fs::OpenOptionsExt; - } -} +cfg_unix! { + use crate::os::unix::fs::OpenOptionsExt; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl OpenOptionsExt for OpenOptions { - fn mode(&mut self, mode: u32) -> &mut Self { - self.0.mode(mode); - self - } + impl OpenOptionsExt for OpenOptions { + fn mode(&mut self, mode: u32) -> &mut Self { + self.0.mode(mode); + self + } - fn custom_flags(&mut self, flags: i32) -> &mut Self { - self.0.custom_flags(flags); - self - } + fn custom_flags(&mut self, flags: i32) -> &mut Self { + self.0.custom_flags(flags); + self } } } diff --git a/src/fs/permissions.rs b/src/fs/permissions.rs index 628dd39..1339a7c 100644 --- a/src/fs/permissions.rs +++ b/src/fs/permissions.rs @@ -1,58 +1,56 @@ -use cfg_if::cfg_if; +cfg_not_docs! { + pub use std::fs::Permissions; +} + +cfg_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: (), + } -cfg_if! { - if #[cfg(feature = "docs")] { - /// A set of permissions on a file or directory. + 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 - #[derive(Clone, PartialEq, Eq, Debug)] - pub struct Permissions { - _private: (), + /// ```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!() } - 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!() - } + /// 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; } } diff --git a/src/future/future.rs b/src/future/future.rs index 556dc1a..8c9c12a 100644 --- a/src/future/future.rs +++ b/src/future/future.rs @@ -1,15 +1,9 @@ -use crate::utils::extension_trait; +extension_trait! { + use std::pin::Pin; + use std::ops::{Deref, DerefMut}; -cfg_if::cfg_if! { - if #[cfg(feature = "docs")] { - use std::pin::Pin; - use std::ops::{Deref, DerefMut}; + use crate::task::{Context, Poll}; - use crate::task::{Context, Poll}; - } -} - -extension_trait! { #[doc = r#" A future represents an asynchronous computation. diff --git a/src/future/into_future.rs b/src/future/into_future.rs index 58b6766..42839a2 100644 --- a/src/future/into_future.rs +++ b/src/future/into_future.rs @@ -30,7 +30,7 @@ use crate::future::Future; /// } /// } /// ``` -#[cfg(any(feature = "unstable", feature = "docs"))] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait IntoFuture { /// The type of value produced on completion. diff --git a/src/future/mod.rs b/src/future/mod.rs index cc3b7a5..a45bf96 100644 --- a/src/future/mod.rs +++ b/src/future/mod.rs @@ -44,12 +44,6 @@ #[doc(inline)] 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 pending::pending; pub use poll_fn::poll_fn; @@ -62,10 +56,10 @@ mod poll_fn; mod ready; mod timeout; -cfg_if! { - if #[cfg(any(feature = "unstable", feature = "docs"))] { - mod into_future; +cfg_unstable! { + #[doc(inline)] + pub use async_macros::{select, try_select}; - pub use into_future::IntoFuture; - } + pub use into_future::IntoFuture; + mod into_future; } diff --git a/src/io/buf_read/mod.rs b/src/io/buf_read/mod.rs index dff10fa..b82971f 100644 --- a/src/io/buf_read/mod.rs +++ b/src/io/buf_read/mod.rs @@ -12,19 +12,12 @@ use read_until::ReadUntilFuture; use std::mem; use std::pin::Pin; -use cfg_if::cfg_if; - use crate::io; use crate::task::{Context, Poll}; -use crate::utils::extension_trait; - -cfg_if! { - if #[cfg(feature = "docs")] { - use std::ops::{Deref, DerefMut}; - } -} extension_trait! { + use std::ops::{Deref, DerefMut}; + #[doc = r#" Allows reading from a buffered byte stream. diff --git a/src/io/read/mod.rs b/src/io/read/mod.rs index 40cb3ca..ed61590 100644 --- a/src/io/read/mod.rs +++ b/src/io/read/mod.rs @@ -13,23 +13,17 @@ use read_to_end::{read_to_end_internal, ReadToEndFuture}; use read_to_string::ReadToStringFuture; use read_vectored::ReadVectoredFuture; -use cfg_if::cfg_if; use std::mem; use crate::io::IoSliceMut; -use crate::utils::extension_trait; -cfg_if! { - if #[cfg(feature = "docs")] { - use std::pin::Pin; - use std::ops::{Deref, DerefMut}; +extension_trait! { + use std::pin::Pin; + use std::ops::{Deref, DerefMut}; - use crate::io; - use crate::task::{Context, Poll}; - } -} + use crate::io; + use crate::task::{Context, Poll}; -extension_trait! { #[doc = r#" Allows reading from a byte stream. @@ -309,34 +303,34 @@ extension_trait! { #[doc = r#" Creates a "by reference" adaptor for this instance of `Read`. - + The returned adaptor also implements `Read` and will simply borrow this current reader. - + # Examples - + [`File`][file]s implement `Read`: - + [file]: ../fs/struct.File.html - + ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::fs::File; - + let mut f = File::open("foo.txt").await?; let mut buffer = Vec::new(); let mut other_buffer = Vec::new(); - + { let reference = f.by_ref(); - + // read at most 5 bytes reference.take(5).read_to_end(&mut buffer).await?; - + } // drop our &mut reference so we can use f again - + // original file still usable, read the rest f.read_to_end(&mut other_buffer).await?; # @@ -348,27 +342,27 @@ extension_trait! { #[doc = r#" Transforms this `Read` instance to a `Stream` over its bytes. - + The returned type implements `Stream` where the `Item` is `Result`. The yielded item is `Ok` if a byte was successfully read and `Err` otherwise. EOF is mapped to returning `None` from this iterator. - + # Examples - + [`File`][file]s implement `Read`: - + [file]: ../fs/struct.File.html - + ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::fs::File; - + let f = File::open("foo.txt").await?; let mut s = f.bytes(); - + while let Some(byte) = s.next().await { println!("{}", byte.unwrap()); } @@ -382,29 +376,29 @@ extension_trait! { #[doc = r#" Creates an adaptor which will chain this stream with another. - + The returned `Read` instance will first read all bytes from this object until EOF is encountered. Afterwards the output is equivalent to the output of `next`. - + # Examples - + [`File`][file]s implement `Read`: - + [file]: ../fs/struct.File.html - + ```no_run # fn main() -> std::io::Result<()> { async_std::task::block_on(async { # use async_std::prelude::*; use async_std::fs::File; - + let f1 = File::open("foo.txt").await?; let f2 = File::open("bar.txt").await?; - + let mut handle = f1.chain(f2); let mut buffer = String::new(); - + // read the value into a String. We could use any Read method here, // this is just one example. handle.read_to_string(&mut buffer).await?; diff --git a/src/io/seek.rs b/src/io/seek/mod.rs similarity index 80% rename from src/io/seek.rs rename to src/io/seek/mod.rs index 2d1c4d3..ec2dd8f 100644 --- a/src/io/seek.rs +++ b/src/io/seek/mod.rs @@ -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::{self, SeekFrom}; -use crate::task::{Context, Poll}; -use crate::utils::extension_trait; - -cfg_if! { - if #[cfg(feature = "docs")] { - use std::ops::{Deref, DerefMut}; - } -} +use crate::io::SeekFrom; extension_trait! { + use std::ops::{Deref, DerefMut}; + use std::pin::Pin; + + use crate::io; + use crate::task::{Context, Poll}; + #[doc = r#" 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 Future for SeekFuture<'_, T> { - type Output = io::Result; - - fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { - let pos = self.pos; - Pin::new(&mut *self.seeker).poll_seek(cx, pos) - } -} diff --git a/src/io/seek/seek.rs b/src/io/seek/seek.rs new file mode 100644 index 0000000..65743be --- /dev/null +++ b/src/io/seek/seek.rs @@ -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 Future for SeekFuture<'_, T> { + type Output = io::Result; + + fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let pos = self.pos; + Pin::new(&mut *self.seeker).poll_seek(cx, pos) + } +} diff --git a/src/io/stderr.rs b/src/io/stderr.rs index 34d4d1d..1ec28b2 100644 --- a/src/io/stderr.rs +++ b/src/io/stderr.rs @@ -1,8 +1,6 @@ use std::pin::Pin; use std::sync::Mutex; -use cfg_if::cfg_if; - use crate::future::Future; use crate::io::{self, Write}; use crate::task::{blocking, Context, JoinHandle, Poll}; @@ -162,35 +160,22 @@ impl Write for Stderr { } } -cfg_if! { - if #[cfg(feature = "docs")] { - 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_unix! { + use crate::os::unix::io::{AsRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for Stderr { - fn as_raw_fd(&self) -> RawFd { - 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_if! { - if #[cfg(any(windows, feature = "docs"))] { - impl AsRawHandle for Stderr { - fn as_raw_handle(&self) -> RawHandle { - std::io::stderr().as_raw_handle() - } +cfg_windows! { + use crate::os::windows::io::{AsRawHandle, RawHandle}; + + impl AsRawHandle for Stderr { + fn as_raw_handle(&self) -> RawHandle { + std::io::stderr().as_raw_handle() } } } diff --git a/src/io/stdin.rs b/src/io/stdin.rs index 178e819..dd3991f 100644 --- a/src/io/stdin.rs +++ b/src/io/stdin.rs @@ -1,8 +1,6 @@ use std::pin::Pin; use std::sync::Mutex; -use cfg_if::cfg_if; - use crate::future::{self, Future}; use crate::io::{self, Read}; use crate::task::{blocking, Context, JoinHandle, Poll}; @@ -186,35 +184,22 @@ impl Read for Stdin { } } -cfg_if! { - if #[cfg(feature = "docs")] { - 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_unix! { + use crate::os::unix::io::{AsRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for Stdin { - fn as_raw_fd(&self) -> RawFd { - 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_if! { - if #[cfg(any(windows, feature = "docs"))] { - impl AsRawHandle for Stdin { - fn as_raw_handle(&self) -> RawHandle { - std::io::stdin().as_raw_handle() - } +cfg_windows! { + use crate::os::windows::io::{AsRawHandle, RawHandle}; + + impl AsRawHandle for Stdin { + fn as_raw_handle(&self) -> RawHandle { + std::io::stdin().as_raw_handle() } } } diff --git a/src/io/stdout.rs b/src/io/stdout.rs index 4128aae..7945bfd 100644 --- a/src/io/stdout.rs +++ b/src/io/stdout.rs @@ -1,8 +1,6 @@ use std::pin::Pin; use std::sync::Mutex; -use cfg_if::cfg_if; - use crate::future::Future; use crate::io::{self, Write}; use crate::task::{blocking, Context, JoinHandle, Poll}; @@ -162,35 +160,22 @@ impl Write for Stdout { } } -cfg_if! { - if #[cfg(feature = "docs")] { - 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_unix! { + use crate::os::unix::io::{AsRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for Stdout { - fn as_raw_fd(&self) -> RawFd { - 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_if! { - if #[cfg(any(windows, feature = "docs"))] { - impl AsRawHandle for Stdout { - fn as_raw_handle(&self) -> RawHandle { - std::io::stdout().as_raw_handle() - } +cfg_windows! { + use crate::os::windows::io::{AsRawHandle, RawHandle}; + + impl AsRawHandle for Stdout { + fn as_raw_handle(&self) -> RawHandle { + std::io::stdout().as_raw_handle() } } } diff --git a/src/io/write/mod.rs b/src/io/write/mod.rs index be69b7e..a07c896 100644 --- a/src/io/write/mod.rs +++ b/src/io/write/mod.rs @@ -10,22 +10,14 @@ use write_all::WriteAllFuture; use write_fmt::WriteFmtFuture; use write_vectored::WriteVectoredFuture; -use cfg_if::cfg_if; +use crate::io::{self, IoSlice}; -use crate::io::IoSlice; -use crate::utils::extension_trait; +extension_trait! { + use std::pin::Pin; + use std::ops::{Deref, DerefMut}; -use crate::io; + use crate::task::{Context, Poll}; -cfg_if! { - if #[cfg(feature = "docs")] { - use std::pin::Pin; - use std::ops::{Deref, DerefMut}; - use crate::task::{Context, Poll}; - } -} - -extension_trait! { #[doc = r#" Allows writing to a byte stream. diff --git a/src/lib.rs b/src/lib.rs index e138c87..7f888a1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,8 @@ #![doc(html_logo_url = "https://async.rs/images/logo--hero.svg")] #![recursion_limit = "1024"] -use cfg_if::cfg_if; +#[macro_use] +mod utils; pub mod fs; pub mod future; @@ -61,26 +62,19 @@ pub mod stream; pub mod sync; pub mod task; -cfg_if! { - if #[cfg(any(feature = "unstable", feature = "docs"))] { - #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - pub mod pin; - #[cfg_attr(feature = "docs", doc(cfg(unstable)))] - pub mod process; +cfg_unstable! { + pub mod pin; + pub mod process; - mod unit; - mod vec; - mod result; - mod option; - mod string; - mod collections; - } + mod unit; + mod vec; + mod result; + mod option; + mod string; + mod collections; + + #[doc(inline)] + pub use std::{write, writeln}; } 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}; diff --git a/src/macros.rs b/src/macros.rs index 12ca7ed..f932e47 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -43,7 +43,7 @@ /// # /// # }) /// ``` -#[cfg(any(feature = "unstable", feature = "docs"))] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[macro_export] 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)))] #[macro_export] 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)))] #[macro_export] 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)))] #[macro_export] macro_rules! eprintln { diff --git a/src/net/addr.rs b/src/net/addr.rs index adc2408..1dada64 100644 --- a/src/net/addr.rs +++ b/src/net/addr.rs @@ -3,24 +3,22 @@ use std::net::{IpAddr, Ipv4Addr, Ipv6Addr}; use std::net::{SocketAddr, SocketAddrV4, SocketAddrV6}; use std::pin::Pin; -use cfg_if::cfg_if; - use crate::future::Future; use crate::io; use crate::task::{blocking, Context, JoinHandle, Poll}; -cfg_if! { - if #[cfg(feature = "docs")] { - #[doc(hidden)] - pub struct ImplFuture(std::marker::PhantomData); +cfg_not_docs! { + macro_rules! ret { + (impl Future, $fut:ty) => ($fut); + } +} + +cfg_docs! { + #[doc(hidden)] + pub struct ImplFuture(std::marker::PhantomData); - macro_rules! ret { - (impl Future, $fut:ty) => (ImplFuture<$out>); - } - } else { - macro_rules! ret { - (impl Future, $fut:ty) => ($fut); - } + macro_rules! ret { + (impl Future, $fut:ty) => (ImplFuture<$out>); } } diff --git a/src/net/tcp/listener.rs b/src/net/tcp/listener.rs index 26e19d7..6fd27f0 100644 --- a/src/net/tcp/listener.rs +++ b/src/net/tcp/listener.rs @@ -1,13 +1,10 @@ use std::net::SocketAddr; use std::pin::Pin; -use cfg_if::cfg_if; - -use super::TcpStream; use crate::future::{self, Future}; use crate::io; use crate::net::driver::Watcher; -use crate::net::ToSocketAddrs; +use crate::net::{TcpStream, ToSocketAddrs}; use crate::stream::Stream; use crate::task::{Context, Poll}; @@ -213,59 +210,46 @@ impl From for TcpListener { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } else if #[cfg(unix)] { - use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - } else if #[cfg(windows)] { - // use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } -} +cfg_unix! { + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for TcpListener { - fn as_raw_fd(&self) -> RawFd { - self.watcher.get_ref().as_raw_fd() - } + impl AsRawFd for TcpListener { + fn as_raw_fd(&self) -> RawFd { + self.watcher.get_ref().as_raw_fd() } + } - impl FromRawFd for TcpListener { - unsafe fn from_raw_fd(fd: RawFd) -> TcpListener { - std::net::TcpListener::from_raw_fd(fd).into() - } + impl FromRawFd for TcpListener { + unsafe fn from_raw_fd(fd: RawFd) -> TcpListener { + std::net::TcpListener::from_raw_fd(fd).into() } + } - impl IntoRawFd for TcpListener { - fn into_raw_fd(self) -> RawFd { - 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_if! { - if #[cfg(any(windows, feature = "docs"))] { - // impl AsRawSocket for TcpListener { - // fn as_raw_socket(&self) -> RawSocket { - // self.raw_socket - // } - // } - // - // impl FromRawSocket for TcpListener { - // unsafe fn from_raw_socket(handle: RawSocket) -> TcpListener { - // net::TcpListener::from_raw_socket(handle).try_into().unwrap() - // } - // } - // - // impl IntoRawSocket for TcpListener { - // fn into_raw_socket(self) -> RawSocket { - // self.raw_socket - // } - // } - } +cfg_windows! { + // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; + // + // impl AsRawSocket for TcpListener { + // fn as_raw_socket(&self) -> RawSocket { + // self.raw_socket + // } + // } + // + // impl FromRawSocket for TcpListener { + // unsafe fn from_raw_socket(handle: RawSocket) -> TcpListener { + // net::TcpListener::from_raw_socket(handle).try_into().unwrap() + // } + // } + // + // impl IntoRawSocket for TcpListener { + // fn into_raw_socket(self) -> RawSocket { + // self.raw_socket + // } + // } } diff --git a/src/net/tcp/stream.rs b/src/net/tcp/stream.rs index 1ffd636..5988194 100644 --- a/src/net/tcp/stream.rs +++ b/src/net/tcp/stream.rs @@ -2,8 +2,6 @@ use std::io::{IoSlice, IoSliceMut, Read as _, Write as _}; use std::net::SocketAddr; use std::pin::Pin; -use cfg_if::cfg_if; - use crate::future; use crate::io::{self, Read, Write}; use crate::net::driver::Watcher; @@ -367,59 +365,46 @@ impl From for TcpStream { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } else if #[cfg(unix)] { - use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - } else if #[cfg(windows)] { - // use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } -} +cfg_unix! { + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for TcpStream { - fn as_raw_fd(&self) -> RawFd { - self.watcher.get_ref().as_raw_fd() - } + impl AsRawFd for TcpStream { + fn as_raw_fd(&self) -> RawFd { + self.watcher.get_ref().as_raw_fd() } + } - impl FromRawFd for TcpStream { - unsafe fn from_raw_fd(fd: RawFd) -> TcpStream { - std::net::TcpStream::from_raw_fd(fd).into() - } + impl FromRawFd for TcpStream { + unsafe fn from_raw_fd(fd: RawFd) -> TcpStream { + std::net::TcpStream::from_raw_fd(fd).into() } + } - impl IntoRawFd for TcpStream { - fn into_raw_fd(self) -> RawFd { - 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_if! { - if #[cfg(any(windows, feature = "docs"))] { - // impl AsRawSocket for TcpStream { - // fn as_raw_socket(&self) -> RawSocket { - // self.raw_socket - // } - // } - // - // impl FromRawSocket for TcpStream { - // unsafe fn from_raw_socket(handle: RawSocket) -> TcpStream { - // net::TcpStream::from_raw_socket(handle).try_into().unwrap() - // } - // } - // - // impl IntoRawSocket for TcpListener { - // fn into_raw_socket(self) -> RawSocket { - // self.raw_socket - // } - // } - } +cfg_windows! { + // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; + // + // impl AsRawSocket for TcpStream { + // fn as_raw_socket(&self) -> RawSocket { + // self.raw_socket + // } + // } + // + // impl FromRawSocket for TcpStream { + // unsafe fn from_raw_socket(handle: RawSocket) -> TcpStream { + // net::TcpStream::from_raw_socket(handle).try_into().unwrap() + // } + // } + // + // impl IntoRawSocket for TcpListener { + // fn into_raw_socket(self) -> RawSocket { + // self.raw_socket + // } + // } } diff --git a/src/net/udp/mod.rs b/src/net/udp/mod.rs index 4588be1..37c9d50 100644 --- a/src/net/udp/mod.rs +++ b/src/net/udp/mod.rs @@ -1,7 +1,5 @@ use std::io; use std::net::SocketAddr; - -use cfg_if::cfg_if; use std::net::{Ipv4Addr, Ipv6Addr}; use crate::future; @@ -463,61 +461,46 @@ impl From for UdpSocket { } } -cfg_if! { - if #[cfg(feature = "docs")] { - use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } else if #[cfg(unix)] { - use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; - } else if #[cfg(windows)] { - // use std::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; - } -} +cfg_unix! { + use crate::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -cfg_if! { - if #[cfg(any(unix, feature = "docs"))] { - impl AsRawFd for UdpSocket { - fn as_raw_fd(&self) -> RawFd { - self.watcher.get_ref().as_raw_fd() - } + impl AsRawFd for UdpSocket { + fn as_raw_fd(&self) -> RawFd { + self.watcher.get_ref().as_raw_fd() } + } - impl FromRawFd for UdpSocket { - unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { - std::net::UdpSocket::from_raw_fd(fd).into() - } + impl FromRawFd for UdpSocket { + unsafe fn from_raw_fd(fd: RawFd) -> UdpSocket { + std::net::UdpSocket::from_raw_fd(fd).into() } + } - impl IntoRawFd for UdpSocket { - fn into_raw_fd(self) -> RawFd { - 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_if! { - 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 { - // self.raw_socket - // } - // } - // - // impl FromRawSocket for UdpSocket { - // 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 { - // self.raw_socket - // } - // } - } +cfg_windows! { + // use crate::os::windows::io::{AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle}; + // + // impl AsRawSocket for UdpSocket { + // fn as_raw_socket(&self) -> RawSocket { + // self.raw_socket + // } + // } + // + // impl FromRawSocket for UdpSocket { + // 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 { + // self.raw_socket + // } + // } } diff --git a/src/os/mod.rs b/src/os/mod.rs index fb9b941..5b836ae 100644 --- a/src/os/mod.rs +++ b/src/os/mod.rs @@ -1,9 +1,9 @@ //! OS-specific extensions. -#[cfg(any(unix, feature = "docs"))] -#[cfg_attr(feature = "docs", doc(cfg(unix)))] -pub mod unix; +cfg_unix! { + pub mod unix; +} -#[cfg(any(windows, feature = "docs"))] -#[cfg_attr(feature = "docs", doc(cfg(windows)))] -pub mod windows; +cfg_windows! { + pub mod windows; +} diff --git a/src/os/unix/fs.rs b/src/os/unix/fs.rs index 4a15510..d3e8523 100644 --- a/src/os/unix/fs.rs +++ b/src/os/unix/fs.rs @@ -1,7 +1,5 @@ //! Unix-specific filesystem extensions. -use cfg_if::cfg_if; - use crate::io; use crate::path::Path; use crate::task::blocking; @@ -31,43 +29,43 @@ pub async fn symlink, Q: AsRef>(src: P, dst: Q) -> io::Resu blocking::spawn(move || std::os::unix::fs::symlink(&src, &dst)).await } -cfg_if! { - if #[cfg(feature = "docs")] { - /// 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; - } +cfg_not_docs! { + pub use std::os::unix::fs::{DirBuilderExt, DirEntryExt, OpenOptionsExt}; +} - /// Unix-specific extension methods for `DirEntry`. - pub trait DirEntryExt { - /// Returns the underlying `d_ino` field in the contained `dirent` - /// structure. - fn ino(&self) -> u64; - } +cfg_docs! { + /// 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`. + pub trait DirEntryExt { + /// Returns the underlying `d_ino` field in the contained `dirent` + /// structure. + fn ino(&self) -> u64; + } - /// Unix-specific extensions to `OpenOptions`. - pub trait OpenOptionsExt { - /// Sets the mode bits that a new file will be created with. - /// - /// If a new file is created as part of a `File::open_opts` call then this - /// 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; + /// Unix-specific extensions to `OpenOptions`. + pub trait OpenOptionsExt { + /// Sets the mode bits that a new file will be created with. + /// + /// If a new file is created as part of a `File::open_opts` call then this + /// 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`. - /// - /// 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; - } - } else { - 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; } } diff --git a/src/os/unix/io.rs b/src/os/unix/io.rs index 820d509..0b98460 100644 --- a/src/os/unix/io.rs +++ b/src/os/unix/io.rs @@ -1,56 +1,54 @@ //! 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! { - if #[cfg(feature = "docs")] { - /// Raw file descriptors. - pub type RawFd = std::os::raw::c_int; +cfg_docs! { + /// Raw file descriptors. + pub type RawFd = std::os::raw::c_int; - /// A trait to extract the raw unix file descriptor from an underlying - /// object. + /// A trait to extract the raw unix file descriptor from an underlying + /// 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 - /// to call the method. Windows platforms have a corresponding `AsRawHandle` - /// and `AsRawSocket` set of traits. - pub trait AsRawFd { - /// 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; - } + /// 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. - pub trait FromRawFd { - /// Constructs a new instance of `Self` from the given raw file - /// descriptor. - /// - /// This function **consumes ownership** of the specified file - /// descriptor. The returned object will take responsibility for closing - /// it when the object goes out of scope. - /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// 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; - } + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// 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 - /// its raw file descriptor. - pub trait IntoRawFd { - /// Consumes this object, returning the raw 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 - /// and must close the descriptor once it's no longer needed. - fn into_raw_fd(self) -> RawFd; - } - } else { - pub use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; + /// A trait to express the ability to consume an object and acquire ownership of + /// its raw file descriptor. + pub trait IntoRawFd { + /// Consumes this object, returning the raw 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 + /// and must close the descriptor once it's no longer needed. + fn into_raw_fd(self) -> RawFd; } } diff --git a/src/os/unix/net/mod.rs b/src/os/unix/net/mod.rs index 2c79e8c..e0a3b9b 100644 --- a/src/os/unix/net/mod.rs +++ b/src/os/unix/net/mod.rs @@ -1,7 +1,5 @@ //! Unix-specific networking extensions. -use cfg_if::cfg_if; - pub use datagram::UnixDatagram; pub use listener::{Incoming, UnixListener}; pub use stream::UnixStream; @@ -10,90 +8,90 @@ mod datagram; mod listener; mod stream; -cfg_if! { - if #[cfg(feature = "docs")] { - use std::fmt; +cfg_not_docs! { + pub use std::os::unix::net::SocketAddr; +} + +cfg_docs! { + use std::fmt; + + use crate::path::Path; - 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: (), + } - /// An address associated with a Unix socket. + impl SocketAddr { + /// Returns `true` if the address is unnamed. /// /// # Examples /// - /// ``` + /// A named address: + /// + /// ```no_run /// use async_std::os::unix::net::UnixListener; /// /// let socket = UnixListener::bind("/tmp/socket").await?; /// let addr = socket.local_addr()?; + /// assert_eq!(addr.is_unnamed(), false); /// ``` - #[derive(Clone)] - pub struct SocketAddr { - _private: (), + /// + /// An unnamed address: + /// + /// ```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 `true` if the address is unnamed. - /// - /// # Examples - /// - /// A named address: - /// - /// ```no_run - /// use async_std::os::unix::net::UnixListener; - /// - /// let socket = UnixListener::bind("/tmp/socket").await?; - /// let addr = socket.local_addr()?; - /// assert_eq!(addr.is_unnamed(), false); - /// ``` - /// - /// An unnamed address: - /// - /// ```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") - } - - /// 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") - } + /// 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 { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - unreachable!("this impl only appears in the rendered docs") - } + impl fmt::Debug for SocketAddr { + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + unreachable!("this impl only appears in the rendered docs") } - } else { - pub use std::os::unix::net::SocketAddr; } } diff --git a/src/os/windows/io.rs b/src/os/windows/io.rs index 20f87d2..e83d557 100644 --- a/src/os/windows/io.rs +++ b/src/os/windows/io.rs @@ -1,50 +1,48 @@ //! 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! { - if #[cfg(feature = "docs")] { - /// Raw HANDLEs. - pub type RawHandle = *mut std::os::raw::c_void; +cfg_docs! { + /// Raw HANDLEs. + pub type RawHandle = *mut std::os::raw::c_void; - /// Raw SOCKETs. - pub type RawSocket = u64; + /// Raw SOCKETs. + pub type RawSocket = u64; - /// Extracts raw handles. - pub trait AsRawHandle { - /// Extracts the raw handle, without taking any ownership. - fn as_raw_handle(&self) -> RawHandle; - } + /// Extracts raw handles. + pub trait AsRawHandle { + /// Extracts the raw handle, without taking any ownership. + fn as_raw_handle(&self) -> RawHandle; + } - /// Construct I/O objects from raw handles. - pub trait FromRawHandle { - /// Constructs a new I/O object from the specified raw handle. - /// - /// This function will **consume ownership** of the handle given, - /// passing responsibility for closing the handle to the returned - /// object. - /// - /// This function is also unsafe as the primitives currently returned - /// have the contract that they are the sole owner of the file - /// descriptor they are wrapping. Usage of this function could - /// accidentally allow violating this contract which can cause memory - /// unsafety in code that relies on it being true. - unsafe fn from_raw_handle(handle: RawHandle) -> Self; - } + /// Construct I/O objects from raw handles. + pub trait FromRawHandle { + /// Constructs a new I/O object from the specified raw handle. + /// + /// This function will **consume ownership** of the handle given, + /// passing responsibility for closing the handle to the returned + /// object. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// accidentally allow violating this contract which can cause memory + /// unsafety in code that relies on it being true. + unsafe fn from_raw_handle(handle: RawHandle) -> Self; + } - /// A trait to express the ability to consume an object and acquire ownership of - /// its raw `HANDLE`. - pub trait IntoRawHandle { - /// Consumes this object, returning the raw underlying handle. - /// - /// This function **transfers ownership** of the underlying handle to the - /// caller. Callers are then the unique owners of the handle and must close - /// it once it's no longer needed. - fn into_raw_handle(self) -> RawHandle; - } - } else { - pub use std::os::windows::io::{ - AsRawHandle, FromRawHandle, IntoRawHandle, RawHandle, RawSocket, - }; + /// A trait to express the ability to consume an object and acquire ownership of + /// its raw `HANDLE`. + pub trait IntoRawHandle { + /// Consumes this object, returning the raw underlying handle. + /// + /// This function **transfers ownership** of the underlying handle to the + /// caller. Callers are then the unique owners of the handle and must close + /// it once it's no longer needed. + fn into_raw_handle(self) -> RawHandle; } } diff --git a/src/pin.rs b/src/pin/mod.rs similarity index 100% rename from src/pin.rs rename to src/pin/mod.rs diff --git a/src/prelude.rs b/src/prelude.rs index 6c670cc..91432e0 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -11,8 +11,6 @@ //! use async_std::prelude::*; //! ``` -use cfg_if::cfg_if; - #[doc(no_inline)] pub use crate::future::Future; #[doc(no_inline)] @@ -41,12 +39,9 @@ pub use crate::io::write::WriteExt as _; #[doc(hidden)] pub use crate::stream::stream::StreamExt as _; -cfg_if! { - if #[cfg(any(feature = "unstable", feature = "docs"))] { - #[doc(no_inline)] - pub use crate::stream::DoubleEndedStream; - - #[doc(no_inline)] - pub use crate::stream::ExactSizeStream; - } +cfg_unstable! { + #[doc(no_inline)] + pub use crate::stream::DoubleEndedStream; + #[doc(no_inline)] + pub use crate::stream::ExactSizeStream; } diff --git a/src/stream/double_ended_stream.rs b/src/stream/double_ended_stream.rs index 6fab77c..129bb1c 100644 --- a/src/stream/double_ended_stream.rs +++ b/src/stream/double_ended_stream.rs @@ -10,8 +10,8 @@ use std::task::{Context, Poll}; /// `Item`s from the back, as well as the front. /// /// [`Stream`]: trait.Stream.html +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[cfg(any(feature = "unstable", feature = "docs"))] pub trait DoubleEndedStream: Stream { /// Removes and returns an element from the end of the stream. /// diff --git a/src/stream/exact_size_stream.rs b/src/stream/exact_size_stream.rs index ef23691..7d2e7cb 100644 --- a/src/stream/exact_size_stream.rs +++ b/src/stream/exact_size_stream.rs @@ -76,8 +76,8 @@ pub use crate::stream::Stream; /// # }); /// # } /// ``` +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[cfg(any(feature = "unstable", feature = "docs"))] pub trait ExactSizeStream: Stream { /// Returns the exact number of times the stream will iterate. /// diff --git a/src/stream/extend.rs b/src/stream/extend.rs index 27efd8b..d9e1481 100644 --- a/src/stream/extend.rs +++ b/src/stream/extend.rs @@ -27,6 +27,7 @@ use crate::stream::IntoStream; /// # /// # }) } /// ``` +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait Extend { /// Extends a collection with the contents of a stream. diff --git a/src/stream/from_stream.rs b/src/stream/from_stream.rs index 047dab8..54a2229 100644 --- a/src/stream/from_stream.rs +++ b/src/stream/from_stream.rs @@ -106,8 +106,8 @@ use std::pin::Pin; ///``` /// /// [`IntoStream`]: trait.IntoStream.html +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[cfg(any(feature = "unstable", feature = "docs"))] pub trait FromStream { /// Creates a value from a stream. /// diff --git a/src/stream/fused_stream.rs b/src/stream/fused_stream.rs index 42e7e6f..e14ab5b 100644 --- a/src/stream/fused_stream.rs +++ b/src/stream/fused_stream.rs @@ -14,7 +14,7 @@ use crate::stream::Stream; /// [`None`]: https://doc.rust-lang.org/std/option/enum.Option.html#variant.None /// [`Stream::fuse`]: trait.Stream.html#method.fuse /// [`Fuse`]: struct.Fuse.html -#[cfg(any(feature = "unstable", feature = "docs"))] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] pub trait FusedStream: Stream {} diff --git a/src/stream/interval.rs b/src/stream/interval.rs index 21ac032..043d307 100644 --- a/src/stream/interval.rs +++ b/src/stream/interval.rs @@ -43,9 +43,8 @@ use futures_timer::Delay; /// # /// # Ok(()) }) } /// ``` -#[cfg(any(feature = "unstable", feature = "docs"))] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[doc(inline)] pub fn interval(dur: Duration) -> Interval { Interval { delay: Delay::new(dur), @@ -55,9 +54,9 @@ pub fn interval(dur: Duration) -> Interval { /// A stream representing notifications at fixed interval /// -#[derive(Debug)] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[doc(inline)] +#[derive(Debug)] pub struct Interval { delay: Delay, interval: Duration, diff --git a/src/stream/into_stream.rs b/src/stream/into_stream.rs index 9233181..f96dc59 100644 --- a/src/stream/into_stream.rs +++ b/src/stream/into_stream.rs @@ -13,8 +13,8 @@ use crate::stream::Stream; /// See also: [`FromStream`]. /// /// [`FromStream`]: trait.FromStream.html +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[cfg(any(feature = "unstable", feature = "docs"))] pub trait IntoStream { /// The type of the elements being iterated over. type Item; diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 3b5f461..e796510 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -21,8 +21,6 @@ //! # }) //! ``` -use cfg_if::cfg_if; - pub use empty::{empty, Empty}; pub use from_fn::{from_fn, FromFn}; pub use once::{once, Once}; @@ -40,28 +38,25 @@ mod once; mod repeat; mod repeat_with; -cfg_if! { - if #[cfg(any(feature = "unstable", feature = "docs"))] { - mod double_ended_stream; - mod exact_size_stream; - mod extend; - mod from_stream; - mod fused_stream; - mod interval; - mod into_stream; - mod product; - mod sum; - - pub use double_ended_stream::DoubleEndedStream; - pub use exact_size_stream::ExactSizeStream; - pub use extend::Extend; - pub use from_stream::FromStream; - pub use fused_stream::FusedStream; - pub use interval::{interval, Interval}; - pub use into_stream::IntoStream; - pub use product::Product; - pub use sum::Sum; +cfg_unstable! { + mod double_ended_stream; + mod exact_size_stream; + mod extend; + mod from_stream; + mod fused_stream; + mod interval; + mod into_stream; + mod product; + mod sum; - pub use stream::Merge; - } + pub use double_ended_stream::DoubleEndedStream; + pub use exact_size_stream::ExactSizeStream; + pub use extend::Extend; + pub use from_stream::FromStream; + pub use fused_stream::FusedStream; + pub use interval::{interval, Interval}; + pub use into_stream::IntoStream; + pub use product::Product; + pub use stream::Merge; + pub use sum::Sum; } diff --git a/src/stream/product.rs b/src/stream/product.rs index b322776..5799990 100644 --- a/src/stream/product.rs +++ b/src/stream/product.rs @@ -11,8 +11,8 @@ use crate::stream::Stream; /// [`product`]: trait.Product.html#tymethod.product /// [`FromStream`]: trait.FromStream.html /// [`Stream::product`]: trait.Stream.html#method.product +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[cfg(any(feature = "unstable", feature = "docs"))] pub trait Product: Sized { /// Method which takes a stream and generates `Self` from the elements by /// multiplying the items. diff --git a/src/stream/stream/merge.rs b/src/stream/stream/merge.rs index ab97d2c..9889dc7 100644 --- a/src/stream/stream/merge.rs +++ b/src/stream/stream/merge.rs @@ -8,7 +8,7 @@ use futures_core::Stream; /// This stream is returned by [`Stream::merge`]. /// /// [`Stream::merge`]: trait.Stream.html#method.merge -#[cfg(any(feature = "unstable", feature = "docs"))] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[derive(Debug)] pub struct Merge { diff --git a/src/stream/stream/mod.rs b/src/stream/stream/mod.rs index 764dc97..501ece1 100644 --- a/src/stream/stream/mod.rs +++ b/src/stream/stream/mod.rs @@ -91,32 +91,22 @@ pub use zip::Zip; use std::cmp::Ordering; use std::marker::PhantomData; -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! { - if #[cfg(feature = "docs")] { - use std::ops::{Deref, DerefMut}; + pub use merge::Merge; - 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; +extension_trait! { + use std::ops::{Deref, DerefMut}; - pub use merge::Merge; - } -} + use crate::task::{Context, Poll}; -extension_trait! { #[doc = r#" An asynchronous stream of values. @@ -495,7 +485,7 @@ extension_trait! { # # }) } ``` - + "#] fn last( self, @@ -1276,7 +1266,7 @@ extension_trait! { [`stream`]: trait.Stream.html#tymethod.next "#] - #[cfg(any(feature = "unstable", feature = "docs"))] + #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[must_use = "if you really need to exhaust the iterator, consider `.for_each(drop)` instead (TODO)"] fn collect<'a, B>( @@ -1315,7 +1305,7 @@ extension_trait! { # }); ``` "#] - #[cfg(any(feature = "unstable", feature = "docs"))] + #[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] fn merge(self, other: U) -> Merge where @@ -1345,9 +1335,9 @@ extension_trait! { let s4 = VecDeque::from(vec![1, 2, 4]); assert_eq!(s1.clone().partial_cmp(s1.clone()).await, Some(Ordering::Equal)); assert_eq!(s1.clone().partial_cmp(s2.clone()).await, Some(Ordering::Less)); - assert_eq!(s2.clone().partial_cmp(s1.clone()).await, Some(Ordering::Greater)); + assert_eq!(s2.clone().partial_cmp(s1.clone()).await, Some(Ordering::Greater)); assert_eq!(s3.clone().partial_cmp(s4.clone()).await, Some(Ordering::Less)); - assert_eq!(s4.clone().partial_cmp(s3.clone()).await, Some(Ordering::Greater)); + assert_eq!(s4.clone().partial_cmp(s3.clone()).await, Some(Ordering::Greater)); # # }) } ``` @@ -1366,7 +1356,7 @@ extension_trait! { #[doc = r#" Lexicographically compares the elements of this `Stream` with those - of another using 'Ord'. + of another using 'Ord'. # Examples @@ -1383,9 +1373,9 @@ extension_trait! { let s4 = VecDeque::from(vec![1, 2, 4]); assert_eq!(s1.clone().cmp(s1.clone()).await, Ordering::Equal); assert_eq!(s1.clone().cmp(s2.clone()).await, Ordering::Less); - assert_eq!(s2.clone().cmp(s1.clone()).await, Ordering::Greater); + assert_eq!(s2.clone().cmp(s1.clone()).await, Ordering::Greater); assert_eq!(s3.clone().cmp(s4.clone()).await, Ordering::Less); - assert_eq!(s4.clone().cmp(s3.clone()).await, Ordering::Greater); + assert_eq!(s4.clone().cmp(s3.clone()).await, Ordering::Greater); # # }) } ``` diff --git a/src/stream/sum.rs b/src/stream/sum.rs index fd5d7d5..a87ade1 100644 --- a/src/stream/sum.rs +++ b/src/stream/sum.rs @@ -11,8 +11,8 @@ use crate::stream::Stream; /// [`sum`]: trait.Sum.html#tymethod.sum /// [`FromStream`]: trait.FromStream.html /// [`Stream::sum`]: trait.Stream.html#method.sum +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] -#[cfg(any(feature = "unstable", feature = "docs"))] pub trait Sum: Sized { /// Method which takes a stream and generates `Self` from the elements by /// "summing up" the items. diff --git a/src/sync/barrier.rs b/src/sync/barrier.rs index 43488ee..080eff8 100644 --- a/src/sync/barrier.rs +++ b/src/sync/barrier.rs @@ -32,6 +32,7 @@ use crate::sync::Mutex; /// # }); /// # } /// ``` +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[derive(Debug)] pub struct Barrier { @@ -61,6 +62,7 @@ struct BarrierState { /// let barrier = Barrier::new(1); /// let barrier_wait_result = barrier.wait(); /// ``` +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[derive(Debug, Clone)] pub struct BarrierWaitResult(bool); diff --git a/src/sync/mod.rs b/src/sync/mod.rs index 3d3b7b8..be74d8f 100644 --- a/src/sync/mod.rs +++ b/src/sync/mod.rs @@ -32,14 +32,13 @@ #[doc(inline)] pub use std::sync::{Arc, Weak}; -#[cfg(any(feature = "unstable", feature = "docs"))] -pub use barrier::{Barrier, BarrierWaitResult}; - pub use mutex::{Mutex, MutexGuard}; pub use rwlock::{RwLock, RwLockReadGuard, RwLockWriteGuard}; -#[cfg(any(feature = "unstable", feature = "docs"))] -#[cfg_attr(feature = "docs", doc(cfg(unstable)))] -mod barrier; mod mutex; mod rwlock; + +cfg_unstable! { + pub use barrier::{Barrier, BarrierWaitResult}; + mod barrier; +} diff --git a/src/task/mod.rs b/src/task/mod.rs index e2c89ae..24eae08 100644 --- a/src/task/mod.rs +++ b/src/task/mod.rs @@ -143,11 +143,9 @@ mod worker; pub(crate) mod blocking; -cfg_if::cfg_if! { - if #[cfg(any(feature = "unstable", feature = "docs"))] { - mod yield_now; - pub use yield_now::yield_now; - } +cfg_unstable! { + mod yield_now; + pub use yield_now::yield_now; } /// Spawns a blocking task. @@ -178,7 +176,7 @@ cfg_if::cfg_if! { /// ``` // Once this function stabilizes we should merge `blocking::spawn` into this so // 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)))] #[inline] pub fn spawn_blocking(f: F) -> task::JoinHandle diff --git a/src/task/yield_now.rs b/src/task/yield_now.rs index 6f59638..2a4788d 100644 --- a/src/task/yield_now.rs +++ b/src/task/yield_now.rs @@ -26,7 +26,7 @@ use std::pin::Pin; /// # /// # }) } /// ``` -#[cfg(any(feature = "unstable", feature = "docs"))] +#[cfg(feature = "unstable")] #[cfg_attr(feature = "docs", doc(cfg(unstable)))] #[inline] pub async fn yield_now() { diff --git a/src/utils.rs b/src/utils.rs index 76db50b..60516d2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -20,6 +20,64 @@ pub fn abort_on_panic(f: impl FnOnce() -> 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. /// /// In generated docs, the base trait will contain methods from the extension trait. In actual @@ -29,7 +87,6 @@ pub fn abort_on_panic(f: impl FnOnce() -> T) -> T { /// 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. #[doc(hidden)] -#[macro_export] macro_rules! extension_trait { ( // Interesting patterns: @@ -113,6 +170,12 @@ macro_rules! extension_trait { // Handle the end of the token list. (@doc ($($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)*); + }; +}