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