1 //! io-lifetimes provides two different options for library authors
2 //! writing APIs which accept untyped I/O resources.
4 //! The following uses the POSIX-ish `Fd` types; similar considerations
5 //! apply to the Windows and portable types.
7 #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
9 #[cfg(all(feature = "close", not(windows)))]
10 use io_lifetimes
::{AsFd, BorrowedFd, IntoFd, OwnedFd}
;
12 /// The simplest way to accept a borrowed I/O resource is to simply use a
13 /// `BorrwedFd` as an argument. This doesn't require the function to have any
14 /// type parameters. It also works in FFI signatures, as `BorrowedFd` and (on
15 /// Rust nightly) `Option<BorrowedFd>` are guaranteed to have the same layout
18 /// Callers with an `AsFd`-implementing type would call `.as_fd()` and pass
20 #[cfg(all(feature = "close", not(windows)))]
21 fn use_fd_a(fd
: BorrowedFd
<'_
>) {
25 /// Another way to do this is to use an `AsFd` type parameter. This is more
26 /// verbose at the function definition site, and entails monomorphization, but
27 /// it has the advantage of allowing users to pass in any type implementing
28 /// `AsFd` directly, without having to call `.as_fd()` themselves.
29 #[cfg(all(feature = "close", not(windows)))]
30 fn use_fd_b
<Fd
: AsFd
>(fd
: Fd
) {
34 /// Another way to do this is to use an `impl AsFd` parameter.
35 #[cfg(all(feature = "close", not(windows)))]
36 fn use_fd_c(fd
: impl AsFd
) {
40 /// The simplest way to accept a consumed I/O resource is to simply use an
41 /// `OwnedFd` as an argument. Similar to `use_fd_a`, this doesn't require the
42 /// function to have any type parameters, and also works in FFI signatures.
44 /// Callers with an `IntoFd`-implementing type would call `.into_fd()` and pass
46 #[cfg(all(feature = "close", not(windows)))]
47 fn consume_fd_a(fd
: OwnedFd
) {
51 /// Another way to do this is to use an `IntoFd` type parameter. Similar to
52 /// `use_fd_b`, this is more verbose here and entails monomorphization, but it
53 /// has the advantage of allowing users to pass in any type implementing
54 /// `IntoFd` directly.
55 #[cfg(all(feature = "close", not(windows)))]
56 fn consume_fd_b
<Fd
: IntoFd
>(fd
: Fd
) {
60 /// Another way to do this is to use an `impl IntoFd` parameter.
61 #[cfg(all(feature = "close", not(windows)))]
62 fn consume_fd_c(fd
: impl IntoFd
) {
66 /// Now let's see how the APIs look for users.
67 #[cfg(all(feature = "close", not(windows)))]
69 let f
= std
::fs
::File
::open("Cargo.toml").unwrap();
71 // The simple option requires an `.as_fd()` at the callsite.
74 // Another option can take a reference to any owning type directly.
77 // Of course, users can still pass in `BorrowedFd` values if they want to.
80 // The other option is `impl AsFd`.
83 // Users can still pass in `BorrowedFd` values if they want to here too.
86 let a
= std
::fs
::File
::open("Cargo.toml").unwrap();
87 let b
= std
::fs
::File
::open("Cargo.toml").unwrap();
88 let c
= std
::fs
::File
::open("Cargo.toml").unwrap();
90 // The simple option requires an `.into_fd()` at the callsite.
91 consume_fd_a(a
.into_fd());
93 // Another option can take any `IntoFd` type directly.
96 // The other option can take any `IntoFd` type directly.
102 println
!("This example uses non-Windows APIs.");
105 #[cfg(all(not(feature = "close"), not(windows)))]
107 println
!("This example requires the \"close\" feature.");