io-lifetimes
A low-level I/O ownership and borrowing library
This library introduces `OwnedFd`, `BorrowedFd`, and supporting types and
traits, and corresponding features for Windows, which implement safe owning
and borrowing I/O lifetime patterns.
This is associated with [RFC 3128], the I/O Safety RFC, which is now merged.
Work is now underway to move the `OwnedFd` and `BorrowedFd` types and `AsFd`
trait developed here into `std`.
Some features currently require nightly Rust, as they depend on `rustc_attrs`
to perform niche optimizations needed for FFI use cases.
For a quick taste, check out the code examples:
- [hello], a basic demo of this API, doing low-level I/O manually, using the
[provided example FFI bindings]
- [easy-conversions], demonstrating the `from_into` convenience feature for
converting from an `impl Into*` into an `impl From*`.
- [portable-views], demonstrating the convenience feature which allows one
to temporarily "view" a file descriptor as any owning type such as `File`
- [flexible-apis], demonstrating how to write library APIs that accept
untyped I/O resources.
- [owning-wrapper], demonstrating how to implement a type which wraps an
`Owned*` type.
[hello]: https://github.com/sunfishcode/io-lifetimes/blob/main/examples/hello.rs
[easy-conversions]: https://github.com/sunfishcode/io-lifetimes/blob/main/examples/easy-conversions.rs
[portable-views]: https://github.com/sunfishcode/io-lifetimes/blob/main/examples/portable-views.rs
[flexible-apis]: https://github.com/sunfishcode/io-lifetimes/blob/main/examples/flexible-apis.rs
[owning-wrapper]: https://github.com/sunfishcode/io-lifetimes/blob/main/examples/owning-wrapper.rs
[provided example FFI bindings]: https://github.com/sunfishcode/io-lifetimes/blob/main/src/example_ffi.rs
The core of the API is very simple, and consists of two main types and three
main traits:
```rust
pub struct BorrowedFd<'fd> { ... }
pub struct OwnedFd { ... }
pub trait AsFd { ... }
pub trait IntoFd { ... }
pub trait FromFd { ... }
impl AsRawFd for BorrowedFd<'_> { ... }
impl AsRawFd for OwnedFd { ... }
impl IntoRawFd for OwnedFd { ... }
impl FromRawFd for OwnedFd { ... }
impl Drop for OwnedFd { ... }
impl AsFd for BorrowedFd<'_> { ... }
impl AsFd for OwnedFd { ... }
impl IntoFd for OwnedFd { ... }
impl FromFd for OwnedFd { ... }
```
On Windows, there are `Handle` and `Socket` versions of every `Fd` thing, and
a special `HandleOrInvalid` type to cope with inconsistent error reporting
in the Windows API.
## The magic of transparency
Here's the fun part. `BorrowedFd` and `OwnedFd` are `repr(transparent)` and
hold `RawFd` values, and `Option