]> git.proxmox.com Git - rustc.git/blob - vendor/io-lifetimes/examples/flexible-apis.rs
New upstream version 1.64.0+dfsg1
[rustc.git] / vendor / io-lifetimes / examples / flexible-apis.rs
1 //! io-lifetimes provides two different options for library authors
2 //! writing APIs which accept untyped I/O resources.
3 //!
4 //! The following uses the POSIX-ish `Fd` types; similar considerations
5 //! apply to the Windows and portable types.
6
7 #![cfg_attr(io_lifetimes_use_std, feature(io_safety))]
8
9 #[cfg(all(feature = "close", not(windows)))]
10 use io_lifetimes::{AsFd, BorrowedFd, IntoFd, OwnedFd};
11
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
16 /// as `RawFd`.
17 ///
18 /// Callers with an `AsFd`-implementing type would call `.as_fd()` and pass
19 /// the result.
20 #[cfg(all(feature = "close", not(windows)))]
21 fn use_fd_a(fd: BorrowedFd<'_>) {
22 let _ = fd;
23 }
24
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) {
31 let _ = fd.as_fd();
32 }
33
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) {
37 let _ = fd.as_fd();
38 }
39
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.
43 ///
44 /// Callers with an `IntoFd`-implementing type would call `.into_fd()` and pass
45 /// the result.
46 #[cfg(all(feature = "close", not(windows)))]
47 fn consume_fd_a(fd: OwnedFd) {
48 let _ = fd;
49 }
50
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) {
57 let _ = fd.into_fd();
58 }
59
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) {
63 let _ = fd.into_fd();
64 }
65
66 /// Now let's see how the APIs look for users.
67 #[cfg(all(feature = "close", not(windows)))]
68 fn main() {
69 let f = std::fs::File::open("Cargo.toml").unwrap();
70
71 // The simple option requires an `.as_fd()` at the callsite.
72 use_fd_a(f.as_fd());
73
74 // Another option can take a reference to any owning type directly.
75 use_fd_b(&f);
76
77 // Of course, users can still pass in `BorrowedFd` values if they want to.
78 use_fd_b(f.as_fd());
79
80 // The other option is `impl AsFd`.
81 use_fd_c(&f);
82
83 // Users can still pass in `BorrowedFd` values if they want to here too.
84 use_fd_c(f.as_fd());
85
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();
89
90 // The simple option requires an `.into_fd()` at the callsite.
91 consume_fd_a(a.into_fd());
92
93 // Another option can take any `IntoFd` type directly.
94 consume_fd_b(b);
95
96 // The other option can take any `IntoFd` type directly.
97 consume_fd_c(c);
98 }
99
100 #[cfg(windows)]
101 fn main() {
102 println!("This example uses non-Windows APIs.");
103 }
104
105 #[cfg(all(not(feature = "close"), not(windows)))]
106 fn main() {
107 println!("This example requires the \"close\" feature.");
108 }