1 //! A simple example implementing the main traits for a type.
2
3 #[cfg(not(windows))]
4 #[cfg(any(feature = "close", not(io_safety_is_in_std)))]
5 use io_lifetimes::FromFd;
6 #[cfg(windows)]
7 #[cfg(any(feature = "close", not(io_safety_is_in_std)))]
8 use io_lifetimes::FromHandle;
9 #[cfg(not(windows))]
10 #[cfg(not(io_safety_is_in_std))]
11 use io_lifetimes::IntoFd;
12 #[cfg(windows)]
13 #[cfg(not(io_safety_is_in_std))]
14 use io_lifetimes::IntoHandle;
15 use io_lifetimes::OwnedFilelike;
16 #[cfg(not(windows))]
17 use io_lifetimes::{AsFd, BorrowedFd, OwnedFd};
18 #[cfg(windows)]
19 use io_lifetimes::{AsHandle, BorrowedHandle, OwnedHandle};
20
21 /// A wrapper around a file descriptor.
22 ///
23 /// Implementing `AsFd`, `IntoFd`, and `FromFd` for a type that wraps an
24 /// `Owned*` is straightforward. `Owned*` types also automatically close the
25 /// handle in its `Drop`.
26 ///
27 /// Should owning wrappers implement `AsRawFd`, `IntoRawFd`, and `FromRawFd`
28 /// too? They can, and there's no need to remove them from a type that already
29 /// implements them. But for new code, they can be omitted. Users that really
30 /// need the raw value can always do `as_fd().as_raw_fd()`,
31 /// `.into_fd().into_raw_fd()`, or `T::from_fd(OwnedFd::from_raw_fd(raw_fd))`.
32 /// But if possible, users should use just `as_fd`, `into_fd`, and `from_fd`
33 /// and avoid working with raw values altogether.
34 struct Thing {
35 filelike: OwnedFilelike,
36 }
37
38 #[cfg(not(windows))]
39 impl AsFd for Thing {
40 #[inline]
as_fdnull41 fn as_fd(&self) -> BorrowedFd<'_> {
42 self.filelike.as_fd()
43 }
44 }
45
46 #[cfg(not(io_safety_is_in_std))]
47 #[cfg(not(windows))]
48 impl IntoFd for Thing {
49 #[inline]
50 fn into_fd(self) -> OwnedFd {
51 self.filelike
52 }
53 }
54
55 #[cfg(not(windows))]
56 impl From<Thing> for OwnedFd {
57 #[inline]
fromnull58 fn from(owned: Thing) -> Self {
59 owned.filelike
60 }
61 }
62
63 #[cfg(not(io_safety_is_in_std))]
64 #[cfg(not(windows))]
65 impl FromFd for Thing {
66 #[inline]
from_fdnull67 fn from_fd(filelike: OwnedFd) -> Self {
68 Self { filelike }
69 }
70 }
71
72 #[cfg(not(windows))]
73 impl From<OwnedFd> for Thing {
74 #[inline]
fromnull75 fn from(filelike: OwnedFd) -> Self {
76 Self { filelike }
77 }
78 }
79
80 #[cfg(windows)]
81 impl AsHandle for Thing {
82 #[inline]
as_handlenull83 fn as_handle(&self) -> BorrowedHandle<'_> {
84 self.filelike.as_handle()
85 }
86 }
87
88 #[cfg(not(io_safety_is_in_std))]
89 #[cfg(windows)]
90 impl IntoHandle for Thing {
91 #[inline]
92 fn into_handle(self) -> OwnedHandle {
93 self.filelike
94 }
95 }
96
97 #[cfg(windows)]
98 impl From<Thing> for OwnedHandle {
99 #[inline]
fromnull100 fn from(owned: Thing) -> Self {
101 owned.filelike
102 }
103 }
104
105 #[cfg(not(io_safety_is_in_std))]
106 #[cfg(windows)]
107 impl FromHandle for Thing {
108 #[inline]
from_handlenull109 fn from_handle(filelike: OwnedHandle) -> Self {
110 Self { filelike }
111 }
112 }
113
114 #[cfg(windows)]
115 impl From<OwnedHandle> for Thing {
116 #[inline]
fromnull117 fn from(filelike: OwnedHandle) -> Self {
118 Self { filelike }
119 }
120 }
121
122 #[cfg(feature = "close")]
mainnull123 fn main() {
124 use io_lifetimes::{AsFilelike, FromFilelike, IntoFilelike};
125
126 // Minimally exercise `Thing`'s Posix-ish API.
127 #[cfg(not(windows))]
128 {
129 let file = std::fs::File::open("Cargo.toml").unwrap();
130 let thing = Thing::from_into_fd(file);
131 let _ = thing.as_fd();
132 let _: OwnedFd = thing.into();
133 }
134
135 // Minimally exercise `Thing`'s Windows API.
136 #[cfg(windows)]
137 {
138 let file = std::fs::File::open("Cargo.toml").unwrap();
139 let thing = Thing::from_into_handle(file);
140 let _ = thing.as_handle();
141 let _: OwnedHandle = thing.into();
142 }
143
144 // Implementing the above traits makes the blanket impls for the portable
145 // `Filelike` traits available too.
146 {
147 let file = std::fs::File::open("Cargo.toml").unwrap();
148 let thing = Thing::from_into_filelike(file);
149 let _ = thing.as_filelike();
150 let _ = thing.into_filelike();
151 }
152 }
153
154 #[cfg(not(feature = "close"))]
mainnull155 fn main() {
156 println!("This example requires the \"close\" feature.");
157 }
158