1
1
mirror of https://github.com/wez/wezterm.git synced 2024-08-17 10:10:23 +03:00

prep for filedescriptor release

This commit is contained in:
Wez Furlong 2019-06-18 23:35:53 -07:00
parent 56a0de9362
commit 240bc8033c
5 changed files with 124 additions and 7 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "filedescriptor"
version = "0.2.0"
version = "0.3.0"
authors = ["Wez Furlong"]
edition = "2018"
repository = "https://github.com/wez/wzsh"
@ -8,6 +8,7 @@ description = "More ergonomic wrappers around RawFd and RawHandle"
license = "MIT"
documentation = "https://docs.rs/filedescriptor"
readme = "README.md"
keywords = ["socketpair", "pipe", "poll", "filedescriptor"]
[dependencies]
failure = "0.1"

View File

@ -1,3 +1,5 @@
<!-- cargo-sync-readme start -->
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.
@ -11,7 +13,7 @@ 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`:
```rust
```
use filedescriptor::{FileDescriptor, FromRawFileDescriptor};
use failure::Fallible;
use std::io::Write;
@ -32,9 +34,9 @@ fn print_something() -> Fallible<()> {
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.
```rust
```
use filedescriptor::Pipe;
use std::io::{Read,Write};
use std::io::{Read, Write};
use failure::Error;
let mut pipe = Pipe::new()?;
@ -44,6 +46,54 @@ 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 failure::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");
```
## 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 failure::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);
```
<!-- cargo-sync-readme end -->

View File

@ -34,7 +34,7 @@
//!
//! ```
//! use filedescriptor::Pipe;
//! use std::io::{Read,Write};
//! use std::io::{Read, Write};
//! use failure::Error;
//!
//! let mut pipe = Pipe::new()?;
@ -46,6 +46,56 @@
//! 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 failure::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 failure::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>(())
//! ```
use failure::Fallible;
#[cfg(unix)]
mod unix;
@ -62,6 +112,9 @@ pub use crate::windows::*;
/// type.
pub trait AsRawFileDescriptor {
fn as_raw_file_descriptor(&self) -> RawFileDescriptor;
fn as_socket_descriptor(&self) -> SocketDescriptor {
self.as_raw_file_descriptor() as SocketDescriptor
}
}
/// `IntoRawFileDescriptor` is a platform independent trait for converting
@ -229,6 +282,9 @@ use std::time::Duration;
/// 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.

View File

@ -10,6 +10,11 @@ use std::os::unix::prelude::*;
/// for avoiding using `cfg` blocks in platform independent code.
pub type RawFileDescriptor = RawFd;
/// `SocketDescriptor` is a platform independent type alias for the
/// underlying platform socket descriptor type. It is primarily useful
/// for avoiding using `cfg` blocks in platform independent code.
pub type SocketDescriptor = RawFd;
impl<T: AsRawFd> AsRawFileDescriptor for T {
fn as_raw_file_descriptor(&self) -> RawFileDescriptor {
self.as_raw_fd()

View File

@ -20,7 +20,7 @@ use winapi::um::winbase::{FILE_TYPE_CHAR, FILE_TYPE_DISK, FILE_TYPE_PIPE};
use winapi::um::winnt::HANDLE;
use winapi::um::winsock2::{
accept, bind, closesocket, connect, getsockname, htonl, listen, WSAPoll, WSASocketW,
WSAStartup, INVALID_SOCKET, SOCK_STREAM, WSADATA, WSA_FLAG_NO_HANDLE_INHERIT,
WSAStartup, INVALID_SOCKET, SOCKET, SOCK_STREAM, WSADATA, WSA_FLAG_NO_HANDLE_INHERIT,
};
pub use winapi::um::winsock2::{POLLERR, POLLHUP, POLLIN, POLLOUT, WSAPOLLFD as pollfd};
@ -29,6 +29,11 @@ pub use winapi::um::winsock2::{POLLERR, POLLHUP, POLLIN, POLLOUT, WSAPOLLFD as p
/// for avoiding using `cfg` blocks in platform independent code.
pub type RawFileDescriptor = RawHandle;
/// `SocketDescriptor` is a platform independent type alias for the
/// underlying platform socket descriptor type. It is primarily useful
/// for avoiding using `cfg` blocks in platform independent code.
pub type SocketDescriptor = SOCKET;
impl<T: AsRawHandle> AsRawFileDescriptor for T {
fn as_raw_file_descriptor(&self) -> RawFileDescriptor {
self.as_raw_handle()