//! The purpose of this crate is to make it a bit more ergonomic for portable
//! applications that need to work with the platform level `RawFd` and
//! `RawHandle` types.
//!
//! Rather than conditionally using `RawFd` and `RawHandle`, the `FileDescriptor`
//! type can be used to manage ownership, duplicate, read and write.
//!
//! ## FileDescriptor
//!
//! This is a bit of a contrived example, but demonstrates how to avoid
//! the conditional code that would otherwise be required to deal with
//! calling `as_raw_fd` and `as_raw_handle`:
//!
//! ```
//! use filedescriptor::{FileDescriptor, FromRawFileDescriptor};
//! use std::io::Write;
//!
//! fn get_stdout() -> anyhow::Result<FileDescriptor> {
//! let stdout = std::io::stdout();
//! let handle = stdout.lock();
//! FileDescriptor::dup(&handle)
//! }
//!
//! fn print_something() -> anyhow::Result<()> {
//! get_stdout()?.write(b"hello")?;
//! Ok(())
//! }
//! ```
//!
//! ## Pipe
//! The `Pipe` type makes it more convenient to create a pipe and manage
//! the lifetime of both the read and write ends of that pipe.
//!
//! ```
//! use filedescriptor::Pipe;
//! use std::io::{Read, Write};
//! use anyhow::Error;
//!
//! let mut pipe = Pipe::new()?;
//! pipe.write.write(b"hello")?;
//! drop(pipe.write);
//!
//! let mut s = String::new();
//! pipe.read.read_to_string(&mut s)?;
//! assert_eq!(s, "hello");
//! # Ok::<(), Error>(())
//! ```
//!
//! ## Socketpair
//! The `socketpair` function returns a pair of connected `SOCK_STREAM`
//! sockets and functions both on posix and windows systems.
//!
//! ```
//! use std::io::{Read, Write};
//! use anyhow::Error;
//!
//! let (mut a, mut b) = filedescriptor::socketpair()?;
//! a.write(b"hello")?;
//! drop(a);
//!
//! let mut s = String::new();
//! b.read_to_string(&mut s)?;
//! assert_eq!(s, "hello");
//! # Ok::<(), Error>(())
//! ```
//!
//! ## Polling
//! The `mio` crate offers powerful and scalable IO multiplexing, but there
//! are some situations where `mio` doesn't fit. The `filedescriptor` crate
//! offers a `poll(2)` compatible interface suitable for testing the readiness
//! of a set of file descriptors. On unix systems this is a very thin wrapper
//! around `poll(2)`, except on macOS where it is actually a wrapper around
//! the `select(2)` interface. On Windows systems the winsock `WSAPoll`
//! function is used instead.
//!
//! ```
//! use filedescriptor::*;
//! use anyhow::Error;
//! use std::time::Duration;
//! use std::io::{Read, Write};
//!
//! let (mut a, mut b) = filedescriptor::socketpair()?;
//! let mut poll_array = [pollfd {
//! fd: a.as_socket_descriptor(),
//! events: POLLIN,
//! revents: 0
//! }];
//! // sleeps for 20 milliseconds because `a` is not yet ready
//! assert_eq!(poll(&mut poll_array, Some(Duration::from_millis(20)))?, 0);
//!
//! b.write(b"hello")?;
//!
//! // Now a is ready for read
//! assert_eq!(poll(&mut poll_array, Some(Duration::from_millis(20)))?, 1);
//!
//! # Ok::<(), Error>(())
//! ```
pub use crate*;
pub use crate*;
/// `AsRawFileDescriptor` is a platform independent trait for returning
/// a non-owning reference to the underlying platform file descriptor
/// type.
/// `IntoRawFileDescriptor` is a platform independent trait for converting
/// an instance into the underlying platform file descriptor type.
/// `FromRawFileDescriptor` is a platform independent trait for creating
/// an instance from the underlying platform file descriptor type.
/// Because the platform file descriptor type has no inherent ownership
/// management, the `from_raw_file_descriptor` function is marked as unsafe
/// to indicate that care must be taken by the caller to ensure that it
/// is used appropriately.
/// `OwnedHandle` allows managing the lifetime of the platform `RawFileDescriptor`
/// type. It is exposed in the interface of this crate primarily for convenience
/// on Windows where the system handle type is used for a variety of objects
/// that don't support reading and writing.
/// `FileDescriptor` is a thin wrapper on top of the `OwnedHandle` type that
/// exposes the ability to Read and Write to the platform `RawFileDescriptor`.
///
/// This is a bit of a contrived example, but demonstrates how to avoid
/// the conditional code that would otherwise be required to deal with
/// calling `as_raw_fd` and `as_raw_handle`:
///
/// ```
/// use filedescriptor::{FileDescriptor, FromRawFileDescriptor};
/// use std::io::Write;
///
/// fn get_stdout() -> anyhow::Result<FileDescriptor> {
/// let stdout = std::io::stdout();
/// let handle = stdout.lock();
/// FileDescriptor::dup(&handle)
/// }
///
/// fn print_something() -> anyhow::Result<()> {
/// get_stdout()?.write(b"hello")?;
/// Ok(())
/// }
/// ```
/// Represents the readable and writable ends of a pair of descriptors
/// connected via a kernel pipe.
///
/// ```
/// use filedescriptor::Pipe;
/// use std::io::{Read,Write};
/// use anyhow::Error;
///
/// let mut pipe = Pipe::new()?;
/// pipe.write.write(b"hello")?;
/// drop(pipe.write);
///
/// let mut s = String::new();
/// pipe.read.read_to_string(&mut s)?;
/// assert_eq!(s, "hello");
/// # Ok::<(), Error>(())
/// ```
use Duration;
/// Examines a set of FileDescriptors to see if some of them are ready for I/O,
/// or if certain events have occurred on them.
///
/// This uses the system native readiness checking mechanism, which on Windows
/// means that it does NOT use IOCP and that this only works with sockets on
/// Windows. If you need IOCP then the `mio` crate is recommended for a much
/// more scalable solution.
///
/// On macOS, the `poll(2)` implementation has problems when used with eg: pty
/// descriptors, so this implementation of poll uses the `select(2)` interface
/// under the covers. That places a limit on the maximum file descriptor value
/// that can be passed to poll. If a file descriptor is out of range then an
/// error will returned. This limitation could potentially be lifted in the
/// future.
///
/// On Windows, `WSAPoll` is used to implement readiness checking, which has
/// the consequence that it can only be used with sockets.
///
/// If `duration` is `None`, then `poll` will block until any of the requested
/// events are ready. Otherwise, `duration` specifies how long to wait for
/// readiness before giving up.
///
/// The return value is the number of entries that were satisfied; `0` means
/// that none were ready after waiting for the specified duration.
///
/// The `pfd` array is mutated and the `revents` field is updated to indicate
/// which of the events were received.
/// Create a pair of connected sockets
///
/// This implementation creates a pair of SOCK_STREAM sockets.