1 | //! Experimental new types and traits to replace the `Raw` family of types and |
2 | //! traits. |
3 | //! |
4 | //! This API has much conceptual similarity with the `Raw` API, but introduces |
5 | //! explicit concepts of ownership and borrowing: |
6 | //! |
7 | //! | `Raw` API | This experimental API | |
8 | //! | ---------- | ------------------------ | |
9 | //! | `Raw*` | `Borrowed*` and `Owned*` | |
10 | //! | `AsRaw*` | `As*` | |
11 | //! | `IntoRaw*` | `Into*` | |
12 | //! | `FromRaw*` | `From*` | |
13 | //! |
14 | //! This gives it several advantages: |
15 | //! |
16 | //! - Less `unsafe` in user code! |
17 | //! |
18 | //! - Easier to understand ownership. |
19 | //! |
20 | //! - It avoids the inconsistency where `AsRawFd` and `IntoRawFd` return |
21 | //! `RawFd` values that users ought to be able to trust, but aren't unsafe, |
22 | //! so it's possible to fail to uphold this trust in purely safe Rust. |
23 | //! |
24 | //! - It enables a number of safe and portable convenience features, such as |
25 | //! [safe typed views] and [from+into conversions]. |
26 | //! |
27 | //! [safe typed views]: AsFilelike::as_filelike_view |
28 | //! [from+into conversions]: FromFilelike::from_into_filelike |
29 | |
30 | #![deny (missing_docs)] |
31 | // Work around <https://github.com/rust-lang/rust/issues/103306>. |
32 | #![cfg_attr (all(wasi_ext, target_os = "wasi" ), feature(wasi_ext))] |
33 | // Currently supported platforms. |
34 | #![cfg (any(unix, windows, target_os = "wasi" , target_os = "hermit" ))] |
35 | |
36 | mod portability; |
37 | mod traits; |
38 | #[cfg (not(io_safety_is_in_std))] |
39 | mod types; |
40 | |
41 | #[cfg (not(io_safety_is_in_std))] |
42 | mod impls_std; |
43 | |
44 | #[cfg (not(io_safety_is_in_std))] |
45 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
46 | pub use traits::AsFd; |
47 | #[cfg (not(io_safety_is_in_std))] |
48 | #[cfg (windows)] |
49 | pub use traits::{AsHandle, AsSocket}; |
50 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
51 | #[allow (deprecated)] |
52 | pub use traits::{FromFd, IntoFd}; |
53 | #[cfg (windows)] |
54 | #[allow (deprecated)] |
55 | pub use traits::{FromHandle, FromSocket, IntoHandle, IntoSocket}; |
56 | |
57 | #[cfg (not(io_safety_is_in_std))] |
58 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
59 | pub use types::{BorrowedFd, OwnedFd}; |
60 | #[cfg (not(io_safety_is_in_std))] |
61 | #[cfg (windows)] |
62 | pub use types::{ |
63 | BorrowedHandle, BorrowedSocket, HandleOrInvalid, InvalidHandleError, NullHandleError, |
64 | OwnedHandle, OwnedSocket, |
65 | }; |
66 | |
67 | #[cfg (io_safety_is_in_std)] |
68 | #[cfg (target_os = "hermit" )] |
69 | pub use std::os::hermit::io::{AsFd, BorrowedFd, OwnedFd}; |
70 | #[cfg (io_safety_is_in_std)] |
71 | #[cfg (unix)] |
72 | pub use std::os::unix::io::{AsFd, BorrowedFd, OwnedFd}; |
73 | #[cfg (io_safety_is_in_std)] |
74 | #[cfg (target_os = "wasi" )] |
75 | pub use std::os::wasi::io::{AsFd, BorrowedFd, OwnedFd}; |
76 | #[cfg (io_safety_is_in_std)] |
77 | #[cfg (windows)] |
78 | pub use std::os::windows::io::{ |
79 | AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, HandleOrInvalid, InvalidHandleError, |
80 | NullHandleError, OwnedHandle, OwnedSocket, |
81 | }; |
82 | |
83 | // io-lifetimes defined `FromFd`/`IntoFd` traits instead of just using |
84 | // `From`/`Into` because that allowed it to implement them for foreign types, |
85 | // including std types like File and TcpStream, and popular third-party types. |
86 | // |
87 | // std just uses `From`/`Into`, because it defines those traits itself so it |
88 | // can implement them for std types itself, and std won't be implementing them |
89 | // for third-party types. However, this means that until `OwnedFd` et al are |
90 | // stabilized, there will be no impls for third-party traits. |
91 | // |
92 | // So we define `FromFd`/`IntoFd` traits, and implement them in terms of |
93 | // `From`/`Into`, |
94 | #[cfg (io_safety_is_in_std)] |
95 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
96 | #[allow (deprecated)] |
97 | impl<T: From<OwnedFd>> FromFd for T { |
98 | #[inline ] |
99 | fn from_fd(owned_fd: OwnedFd) -> Self { |
100 | owned_fd.into() |
101 | } |
102 | } |
103 | #[cfg (io_safety_is_in_std)] |
104 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
105 | #[allow (deprecated)] |
106 | impl<T> IntoFd for T |
107 | where |
108 | OwnedFd: From<T>, |
109 | { |
110 | #[inline ] |
111 | fn into_fd(self) -> OwnedFd { |
112 | self.into() |
113 | } |
114 | } |
115 | |
116 | #[cfg (io_safety_is_in_std)] |
117 | #[cfg (windows)] |
118 | #[allow (deprecated)] |
119 | impl<T: From<OwnedHandle>> FromHandle for T { |
120 | #[inline ] |
121 | fn from_handle(owned_handle: OwnedHandle) -> Self { |
122 | owned_handle.into() |
123 | } |
124 | } |
125 | #[cfg (io_safety_is_in_std)] |
126 | #[cfg (windows)] |
127 | #[allow (deprecated)] |
128 | impl<T> IntoHandle for T |
129 | where |
130 | OwnedHandle: From<T>, |
131 | { |
132 | #[inline ] |
133 | fn into_handle(self) -> OwnedHandle { |
134 | self.into() |
135 | } |
136 | } |
137 | |
138 | #[cfg (io_safety_is_in_std)] |
139 | #[cfg (windows)] |
140 | #[allow (deprecated)] |
141 | impl<T: From<OwnedSocket>> FromSocket for T { |
142 | #[inline ] |
143 | fn from_socket(owned_socket: OwnedSocket) -> Self { |
144 | owned_socket.into() |
145 | } |
146 | } |
147 | #[cfg (io_safety_is_in_std)] |
148 | #[cfg (windows)] |
149 | #[allow (deprecated)] |
150 | impl<T> IntoSocket for T |
151 | where |
152 | OwnedSocket: From<T>, |
153 | { |
154 | #[inline ] |
155 | fn into_socket(self) -> OwnedSocket { |
156 | self.into() |
157 | } |
158 | } |
159 | |
160 | pub use portability::{ |
161 | AsFilelike, AsSocketlike, BorrowedFilelike, BorrowedSocketlike, FromFilelike, FromSocketlike, |
162 | IntoFilelike, IntoSocketlike, OwnedFilelike, OwnedSocketlike, |
163 | }; |
164 | |
165 | #[cfg (feature = "close" )] |
166 | pub mod example_ffi; |
167 | pub mod raw; |
168 | pub mod views; |
169 | |
170 | // Ideally, we'd want crates to implement our traits themselves. But for now, |
171 | // while we're prototyping, we provide a few impls on foreign types. |
172 | #[cfg (not(io_safety_is_in_std))] |
173 | #[cfg (feature = "async-std" )] |
174 | mod impls_async_std; |
175 | #[cfg (not(io_safety_is_in_std))] |
176 | #[cfg (feature = "fs-err" )] |
177 | mod impls_fs_err; |
178 | #[cfg (not(io_safety_is_in_std))] |
179 | #[cfg (feature = "mio" )] |
180 | mod impls_mio; |
181 | #[cfg (not(target_os = "wasi" ))] |
182 | #[cfg (not(io_safety_is_in_std))] |
183 | #[cfg (feature = "os_pipe" )] |
184 | mod impls_os_pipe; |
185 | #[cfg (not(io_safety_is_in_std))] |
186 | #[cfg (feature = "socket2" )] |
187 | mod impls_socket2; |
188 | #[cfg (not(io_safety_is_in_std))] |
189 | #[cfg (feature = "tokio" )] |
190 | mod impls_tokio; |
191 | |