/rust/registry/src/index.crates.io-1949cf8c6b5b557f/io-lifetimes-2.0.4/src/views.rs
Line | Count | Source |
1 | | //! Typed views using temporary objects. |
2 | | //! |
3 | | //! This module defines the return types for [`AsFilelike::as_filelike_view`] |
4 | | //! and [`AsSocketlike::as_socketlike_view`]. |
5 | | //! |
6 | | //! [`AsSocketlike::as_socketlike_view`]: crate::AsSocketlike::as_socketlike_view |
7 | | |
8 | | use crate::raw::{ |
9 | | AsRawFilelike, AsRawSocketlike, FromRawFilelike, FromRawSocketlike, IntoRawFilelike, |
10 | | IntoRawSocketlike, RawFilelike, RawSocketlike, |
11 | | }; |
12 | | #[cfg(any(unix, target_os = "wasi", target_os = "hermit"))] |
13 | | use crate::OwnedFd; |
14 | | use crate::{ |
15 | | AsFilelike, AsSocketlike, FromFilelike, FromSocketlike, IntoFilelike, IntoSocketlike, |
16 | | OwnedFilelike, OwnedSocketlike, |
17 | | }; |
18 | | #[cfg(windows)] |
19 | | use crate::{OwnedHandle, OwnedSocket}; |
20 | | use std::fmt; |
21 | | use std::marker::PhantomData; |
22 | | use std::mem::ManuallyDrop; |
23 | | use std::ops::Deref; |
24 | | |
25 | | /// Declare that a type is safe to use in a [`FilelikeView`]. |
26 | | /// |
27 | | /// # Safety |
28 | | /// |
29 | | /// Types implementing this trait declare that if they are constructed with |
30 | | /// [`FromFilelike`] and consumed with [`IntoFilelike`], their `IntoFilelike` |
31 | | /// will return the same `OwnedFd` value that was passed to their |
32 | | /// `FromFilelike`. |
33 | | pub unsafe trait FilelikeViewType: FromFilelike + IntoFilelike {} |
34 | | |
35 | | /// Declare that a type is safe to use in a [`SocketlikeView`]. |
36 | | /// |
37 | | /// # Safety |
38 | | /// |
39 | | /// Types implementing this trait declare that if they are constructed with |
40 | | /// [`FromSocketlike`] and consumed with [`IntoSocketlike`], their |
41 | | /// `IntoSocketlike` will return the same `OwnedFd` value that was passed to |
42 | | /// their `FromSocketlike`. |
43 | | pub unsafe trait SocketlikeViewType: FromSocketlike + IntoSocketlike {} |
44 | | |
45 | | /// A non-owning view of a resource which dereferences to a `&Target` or |
46 | | /// `&mut Target`. These are returned by [`AsFilelike::as_filelike_view`]. |
47 | | pub struct FilelikeView<'filelike, Target: FilelikeViewType> { |
48 | | /// The value to dereference to. This is a `ManuallyDrop` so that we can |
49 | | /// consume it in our `Drop` impl. |
50 | | target: ManuallyDrop<Target>, |
51 | | |
52 | | /// `FilelikeViewType` implementors guarantee that their `Into<OwnedFd>` |
53 | | /// returns the same fd as their `From<OwnedFd>` gave them. This field |
54 | | /// allows us to verify this. |
55 | | #[cfg(debug_assertions)] |
56 | | orig: RawFilelike, |
57 | | |
58 | | /// This field exists because we don't otherwise explicitly use |
59 | | /// `'filelike`. |
60 | | _phantom: PhantomData<&'filelike OwnedFilelike>, |
61 | | } |
62 | | |
63 | | /// A non-owning view of a resource which dereferences to a `&Target` or |
64 | | /// `&mut Target`. These are returned by [`AsSocketlike::as_socketlike_view`]. |
65 | | pub struct SocketlikeView<'socketlike, Target: SocketlikeViewType> { |
66 | | /// The value to dereference to. This is a `ManuallyDrop` so that we can |
67 | | /// consume it in our `Drop` impl. |
68 | | target: ManuallyDrop<Target>, |
69 | | |
70 | | /// `SocketlikeViewType` implementors guarantee that their `Into<OwnedFd>` |
71 | | /// returns the same fd as their `From<OwnedFd>` gave them. This field |
72 | | /// allows us to verify this. |
73 | | #[cfg(debug_assertions)] |
74 | | orig: RawSocketlike, |
75 | | |
76 | | /// This field exists because we don't otherwise explicitly use |
77 | | /// `'socketlike`. |
78 | | _phantom: PhantomData<&'socketlike OwnedSocketlike>, |
79 | | } |
80 | | |
81 | | impl<Target: FilelikeViewType> FilelikeView<'_, Target> { |
82 | | /// Construct a temporary `Target` and wrap it in a `FilelikeView` object. |
83 | | #[inline] |
84 | 0 | pub(crate) fn new<T: AsFilelike>(filelike: &T) -> Self { |
85 | | // Safety: The returned `FilelikeView` is scoped to the lifetime of |
86 | | // `filelike`, which we've borrowed here, so the view won't outlive |
87 | | // the object it's borrowed from. |
88 | 0 | unsafe { Self::view_raw(filelike.as_filelike().as_raw_filelike()) } |
89 | 0 | } Unexecuted instantiation: <io_lifetimes::views::FilelikeView<std::fs::File>>::new::<std::fs::File> Unexecuted instantiation: <io_lifetimes::views::FilelikeView<std::fs::File>>::new::<std::os::fd::owned::BorrowedFd> |
90 | | |
91 | | /// Construct a temporary `Target` from raw and wrap it in a `FilelikeView` |
92 | | /// object. |
93 | | /// |
94 | | /// # Safety |
95 | | /// |
96 | | /// `raw` must be a valid raw filelike referencing a resource that outlives |
97 | | /// the resulting view. |
98 | | #[inline] |
99 | 0 | pub unsafe fn view_raw(raw: RawFilelike) -> Self { |
100 | 0 | let owned = OwnedFilelike::from_raw_filelike(raw); |
101 | 0 | Self { |
102 | 0 | target: ManuallyDrop::new(Target::from_filelike(owned)), |
103 | 0 | #[cfg(debug_assertions)] |
104 | 0 | orig: raw, |
105 | 0 | _phantom: PhantomData, |
106 | 0 | } |
107 | 0 | } |
108 | | } |
109 | | |
110 | | impl<Target: SocketlikeViewType> SocketlikeView<'_, Target> { |
111 | | /// Construct a temporary `Target` and wrap it in a `SocketlikeView` |
112 | | /// object. |
113 | | #[inline] |
114 | | pub(crate) fn new<T: AsSocketlike>(socketlike: &T) -> Self { |
115 | | // Safety: The returned `SocketlikeView` is scoped to the lifetime of |
116 | | // `socketlike`, which we've borrowed here, so the view won't outlive |
117 | | // the object it's borrowed from. |
118 | | unsafe { Self::view_raw(socketlike.as_socketlike().as_raw_socketlike()) } |
119 | | } |
120 | | |
121 | | /// Construct a temporary `Target` from raw and wrap it in a |
122 | | /// `SocketlikeView` object. |
123 | | /// |
124 | | /// # Safety |
125 | | /// |
126 | | /// `raw` must be a valid raw socketlike referencing a resource that |
127 | | /// outlives the resulting view. |
128 | | #[inline] |
129 | | pub unsafe fn view_raw(raw: RawSocketlike) -> Self { |
130 | | let owned = OwnedSocketlike::from_raw_socketlike(raw); |
131 | | Self { |
132 | | target: ManuallyDrop::new(Target::from_socketlike(owned)), |
133 | | #[cfg(debug_assertions)] |
134 | | orig: raw, |
135 | | _phantom: PhantomData, |
136 | | } |
137 | | } |
138 | | } |
139 | | |
140 | | impl<Target: FilelikeViewType> Deref for FilelikeView<'_, Target> { |
141 | | type Target = Target; |
142 | | |
143 | | #[inline] |
144 | 0 | fn deref(&self) -> &Self::Target { |
145 | 0 | &self.target |
146 | 0 | } |
147 | | } |
148 | | |
149 | | impl<Target: SocketlikeViewType> Deref for SocketlikeView<'_, Target> { |
150 | | type Target = Target; |
151 | | |
152 | | #[inline] |
153 | | fn deref(&self) -> &Self::Target { |
154 | | &self.target |
155 | | } |
156 | | } |
157 | | |
158 | | impl<Target: FilelikeViewType> Drop for FilelikeView<'_, Target> { |
159 | | #[inline] |
160 | 0 | fn drop(&mut self) { |
161 | | // Use `Into*` to consume `self.target` without freeing its resource. |
162 | | // |
163 | | // Safety: Using `ManuallyDrop::take` requires us to ensure that |
164 | | // `self.target` is not used again. We don't use it again here, and |
165 | | // this is the `drop` function, so we know it's not used afterward. |
166 | 0 | let _raw = unsafe { ManuallyDrop::take(&mut self.target) } |
167 | 0 | .into_filelike() |
168 | 0 | .into_raw_filelike(); |
169 | | |
170 | | #[cfg(debug_assertions)] |
171 | | debug_assert_eq!(self.orig, _raw); |
172 | 0 | } |
173 | | } |
174 | | |
175 | | impl<Target: SocketlikeViewType> Drop for SocketlikeView<'_, Target> { |
176 | | #[inline] |
177 | | fn drop(&mut self) { |
178 | | // Use `Into*` to consume `self.target` without freeing its resource. |
179 | | // |
180 | | // Safety: Using `ManuallyDrop::take` requires us to ensure that |
181 | | // `self.target` is not used again. We don't use it again here, and |
182 | | // this is the `drop` function, so we know it's not used afterward. |
183 | | let _raw = unsafe { ManuallyDrop::take(&mut self.target) } |
184 | | .into_socketlike() |
185 | | .into_raw_socketlike(); |
186 | | |
187 | | #[cfg(debug_assertions)] |
188 | | debug_assert_eq!(self.orig, _raw); |
189 | | } |
190 | | } |
191 | | |
192 | | impl<Target: FilelikeViewType> fmt::Debug for FilelikeView<'_, Target> { |
193 | | #[allow(clippy::missing_inline_in_public_items)] |
194 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
195 | | f.debug_struct("FilelikeView") |
196 | | .field("target", &*self) |
197 | | .finish() |
198 | | } |
199 | | } |
200 | | |
201 | | impl<Target: SocketlikeViewType> fmt::Debug for SocketlikeView<'_, Target> { |
202 | | #[allow(clippy::missing_inline_in_public_items)] |
203 | | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
204 | | f.debug_struct("SocketlikeView") |
205 | | .field("target", &*self) |
206 | | .finish() |
207 | | } |
208 | | } |
209 | | |
210 | | #[cfg(any(unix, target_os = "wasi", target_os = "hermit"))] |
211 | | unsafe impl FilelikeViewType for OwnedFd {} |
212 | | #[cfg(windows)] |
213 | | unsafe impl FilelikeViewType for OwnedHandle {} |
214 | | #[cfg(windows)] |
215 | | unsafe impl SocketlikeViewType for OwnedSocket {} |
216 | | unsafe impl FilelikeViewType for std::fs::File {} |
217 | | unsafe impl SocketlikeViewType for std::net::TcpStream {} |
218 | | unsafe impl SocketlikeViewType for std::net::TcpListener {} |
219 | | unsafe impl SocketlikeViewType for std::net::UdpSocket {} |
220 | | #[cfg(unix)] |
221 | | unsafe impl SocketlikeViewType for std::os::unix::net::UnixStream {} |
222 | | #[cfg(unix)] |
223 | | unsafe impl SocketlikeViewType for std::os::unix::net::UnixListener {} |
224 | | |
225 | | #[cfg(unix)] |
226 | | unsafe impl SocketlikeViewType for std::os::unix::net::UnixDatagram {} |
227 | | #[cfg(not(any(target_os = "wasi", target_os = "hermit")))] |
228 | | #[cfg(feature = "os_pipe")] |
229 | | unsafe impl FilelikeViewType for os_pipe::PipeWriter {} |
230 | | #[cfg(not(any(target_os = "wasi", target_os = "hermit")))] |
231 | | #[cfg(feature = "os_pipe")] |
232 | | unsafe impl FilelikeViewType for os_pipe::PipeReader {} |
233 | | |
234 | | #[cfg(not(any(target_os = "wasi", target_os = "hermit")))] |
235 | | #[cfg(feature = "socket2")] |
236 | | unsafe impl SocketlikeViewType for socket2::Socket {} |
237 | | |
238 | | #[cfg(not(any(target_os = "wasi", target_os = "hermit")))] |
239 | | #[cfg(feature = "async-std")] |
240 | | unsafe impl SocketlikeViewType for async_std::net::TcpStream {} |
241 | | #[cfg(not(any(target_os = "wasi", target_os = "hermit")))] |
242 | | #[cfg(feature = "async-std")] |
243 | | unsafe impl SocketlikeViewType for async_std::net::TcpListener {} |
244 | | #[cfg(not(any(target_os = "wasi", target_os = "hermit")))] |
245 | | #[cfg(feature = "async-std")] |
246 | | unsafe impl SocketlikeViewType for async_std::net::UdpSocket {} |
247 | | #[cfg(unix)] |
248 | | #[cfg(feature = "async-std")] |
249 | | unsafe impl SocketlikeViewType for async_std::os::unix::net::UnixStream {} |
250 | | #[cfg(unix)] |
251 | | #[cfg(feature = "async-std")] |
252 | | unsafe impl SocketlikeViewType for async_std::os::unix::net::UnixListener {} |
253 | | #[cfg(unix)] |
254 | | #[cfg(feature = "async-std")] |
255 | | unsafe impl SocketlikeViewType for async_std::os::unix::net::UnixDatagram {} |
256 | | |
257 | | #[cfg(feature = "mio")] |
258 | | unsafe impl SocketlikeViewType for mio::net::TcpStream {} |
259 | | #[cfg(feature = "mio")] |
260 | | unsafe impl SocketlikeViewType for mio::net::TcpListener {} |
261 | | #[cfg(feature = "mio")] |
262 | | unsafe impl SocketlikeViewType for mio::net::UdpSocket {} |
263 | | #[cfg(unix)] |
264 | | #[cfg(feature = "mio")] |
265 | | unsafe impl SocketlikeViewType for mio::net::UnixDatagram {} |
266 | | #[cfg(unix)] |
267 | | #[cfg(feature = "mio")] |
268 | | unsafe impl SocketlikeViewType for mio::net::UnixListener {} |
269 | | #[cfg(unix)] |
270 | | #[cfg(feature = "mio")] |
271 | | unsafe impl SocketlikeViewType for mio::net::UnixStream {} |
272 | | #[cfg(unix)] |
273 | | #[cfg(feature = "mio")] |
274 | | unsafe impl FilelikeViewType for mio::unix::pipe::Receiver {} |
275 | | #[cfg(unix)] |
276 | | #[cfg(feature = "mio")] |
277 | | unsafe impl FilelikeViewType for mio::unix::pipe::Sender {} |