1 | //! Portability abstractions over `Owned*` and `Borrowed*`. |
2 | //! |
3 | //! On Unix, "everything is a file descriptor". On Windows, file/pipe/process |
4 | //! handles are distinct from socket descriptors. This file provides a minimal |
5 | //! layer of portability over this difference. |
6 | |
7 | use crate::views::{FilelikeView, FilelikeViewType, SocketlikeView, SocketlikeViewType}; |
8 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
9 | use crate::{AsFd, BorrowedFd, OwnedFd}; |
10 | #[cfg (windows)] |
11 | use crate::{AsHandle, AsSocket, BorrowedHandle, BorrowedSocket, OwnedHandle, OwnedSocket}; |
12 | |
13 | /// A reference to a filelike object. |
14 | /// |
15 | /// This is a portability abstraction over Unix-like [`BorrowedFd`] and |
16 | /// Windows' `BorrowedHandle`. |
17 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
18 | pub type BorrowedFilelike<'filelike> = BorrowedFd<'filelike>; |
19 | |
20 | /// A reference to a filelike object. |
21 | /// |
22 | /// This is a portability abstraction over Unix-like `BorrowedFd` and |
23 | /// Windows' [`BorrowedHandle`]. |
24 | #[cfg (windows)] |
25 | pub type BorrowedFilelike<'filelike> = BorrowedHandle<'filelike>; |
26 | |
27 | /// A reference to a socketlike object. |
28 | /// |
29 | /// This is a portability abstraction over Unix-like [`BorrowedFd`] and |
30 | /// Windows' `BorrowedSocket`. |
31 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
32 | pub type BorrowedSocketlike<'socketlike> = BorrowedFd<'socketlike>; |
33 | |
34 | /// A reference to a socketlike object. |
35 | /// |
36 | /// This is a portability abstraction over Unix-like `BorrowedFd` and |
37 | /// Windows' [`BorrowedSocket`]. |
38 | #[cfg (windows)] |
39 | pub type BorrowedSocketlike<'socketlike> = BorrowedSocket<'socketlike>; |
40 | |
41 | /// An owned filelike object. |
42 | /// |
43 | /// This is a portability abstraction over Unix-like [`OwnedFd`] and |
44 | /// Windows' `OwnedHandle`. |
45 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
46 | pub type OwnedFilelike = OwnedFd; |
47 | |
48 | /// An owned filelike object. |
49 | /// |
50 | /// This is a portability abstraction over Unix-like `OwnedFd` and |
51 | /// Windows' [`OwnedHandle`]. |
52 | #[cfg (windows)] |
53 | pub type OwnedFilelike = OwnedHandle; |
54 | |
55 | /// An owned socketlike object. |
56 | /// |
57 | /// This is a portability abstraction over Unix-like [`OwnedFd`] and |
58 | /// Windows' `OwnedSocket`. |
59 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
60 | pub type OwnedSocketlike = OwnedFd; |
61 | |
62 | /// An owned socketlike object. |
63 | /// |
64 | /// This is a portability abstraction over Unix-like `OwnedFd` and |
65 | /// Windows' [`OwnedSocket`]. |
66 | #[cfg (windows)] |
67 | pub type OwnedSocketlike = OwnedSocket; |
68 | |
69 | /// A portable trait to borrow a reference from an underlying filelike object. |
70 | /// |
71 | /// This is a portability abstraction over Unix-like [`AsFd`] and Windows' |
72 | /// `AsHandle`. It also provides the `as_filelike_view` convenience function |
73 | /// providing typed views. |
74 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
75 | pub trait AsFilelike: AsFd { |
76 | /// Borrows the reference. |
77 | /// |
78 | /// # Example |
79 | /// |
80 | /// ```rust,no_run |
81 | /// use std::fs::File; |
82 | /// # use std::io; |
83 | /// use io_lifetimes::{AsFilelike, BorrowedFilelike}; |
84 | /// |
85 | /// let mut f = File::open("foo.txt" )?; |
86 | /// let borrowed_filelike: BorrowedFilelike<'_> = f.as_filelike(); |
87 | /// # Ok::<(), io::Error>(()) |
88 | /// ``` |
89 | fn as_filelike(&self) -> BorrowedFilelike<'_>; |
90 | |
91 | /// Return a borrowing view of a resource which dereferences to a |
92 | /// `&Target`. |
93 | /// |
94 | /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some |
95 | /// cases, such as [`File`], `Read` and `Write` are implemented for |
96 | /// `&Target` in addition to `Target`, and you can get a `&mut &Target` |
97 | /// by doing `&*` on the resuting view, like this: |
98 | /// |
99 | /// ```rust,ignore |
100 | /// let v = f.as_filelike_view::<std::fs::File>(); |
101 | /// (&*v).read(&mut buf).unwrap(); |
102 | /// ``` |
103 | /// |
104 | /// [`File`]: std::fs::File |
105 | /// [`Read`]: std::io::Read |
106 | /// [`Write`]: std::io::Write |
107 | fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>; |
108 | } |
109 | |
110 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
111 | impl<T: AsFd> AsFilelike for T { |
112 | #[inline ] |
113 | fn as_filelike(&self) -> BorrowedFilelike<'_> { |
114 | self.as_fd() |
115 | } |
116 | |
117 | #[inline ] |
118 | fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target> { |
119 | FilelikeView::new(self) |
120 | } |
121 | } |
122 | |
123 | /// A portable trait to borrow a reference from an underlying filelike object. |
124 | /// |
125 | /// This is a portability abstraction over Unix-like `AsFd` and Windows' |
126 | /// [`AsHandle`]. It also provides the `as_filelike_view` convenience function |
127 | /// providing typed views. |
128 | #[cfg (windows)] |
129 | pub trait AsFilelike: AsHandle { |
130 | /// Borrows the reference. |
131 | /// |
132 | /// # Example |
133 | /// |
134 | /// ```rust,no_run |
135 | /// use std::fs::File; |
136 | /// # use std::io; |
137 | /// use io_lifetimes::{AsFilelike, BorrowedFilelike}; |
138 | /// |
139 | /// let mut f = File::open("foo.txt")?; |
140 | /// let borrowed_filelike: BorrowedFilelike<'_> = f.as_filelike(); |
141 | /// # Ok::<(), io::Error>(()) |
142 | /// ``` |
143 | fn as_filelike(&self) -> BorrowedFilelike<'_>; |
144 | |
145 | /// Return a borrowing view of a resource which dereferences to a |
146 | /// `&Target`. |
147 | /// |
148 | /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some |
149 | /// cases, such as [`File`], `Read` and `Write` are implemented for |
150 | /// `&Target` in addition to `Target`, and you can get a `&mut &Target` |
151 | /// by doing `&*` on the resuting view, like this: |
152 | /// |
153 | /// ```rust,ignore |
154 | /// let v = f.as_filelike_view::<std::fs::File>(); |
155 | /// (&*v).read(&mut buf).unwrap(); |
156 | /// ``` |
157 | /// |
158 | /// [`File`]: std::fs::File |
159 | /// [`Read`]: std::io::Read |
160 | /// [`Write`]: std::io::Write |
161 | fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>; |
162 | } |
163 | |
164 | #[cfg (windows)] |
165 | impl<T: AsHandle> AsFilelike for T { |
166 | #[inline ] |
167 | fn as_filelike(&self) -> BorrowedFilelike<'_> { |
168 | self.as_handle() |
169 | } |
170 | |
171 | #[inline ] |
172 | fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target> { |
173 | FilelikeView::new(self) |
174 | } |
175 | } |
176 | |
177 | /// A portable trait to borrow a reference from an underlying socketlike |
178 | /// object. |
179 | /// |
180 | /// This is a portability abstraction over Unix-like [`AsFd`] and Windows' |
181 | /// `AsSocket`. It also provides the `as_socketlike_view` convenience |
182 | /// function providing typed views. |
183 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
184 | pub trait AsSocketlike: AsFd { |
185 | /// Borrows the reference. |
186 | fn as_socketlike(&self) -> BorrowedSocketlike<'_>; |
187 | |
188 | /// Return a borrowing view of a resource which dereferences to a |
189 | /// `&Target`. |
190 | /// |
191 | /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some |
192 | /// cases, such as [`TcpStream`], `Read` and `Write` are implemented |
193 | /// for `&Target` in addition to `Target`, and you can get a `&mut |
194 | /// &Target` by doing `&*` on the resuting view, like this: |
195 | /// |
196 | /// ```rust,ignore |
197 | /// let v = s.as_socketlike_view::<std::net::TcpStream>(); |
198 | /// (&*v).read(&mut buf).unwrap(); |
199 | /// ``` |
200 | /// |
201 | /// [`TcpStream`]: std::net::TcpStream |
202 | /// [`Read`]: std::io::Read |
203 | /// [`Write`]: std::io::Write |
204 | fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>; |
205 | } |
206 | |
207 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
208 | impl<T: AsFd> AsSocketlike for T { |
209 | #[inline ] |
210 | fn as_socketlike(&self) -> BorrowedSocketlike<'_> { |
211 | self.as_fd() |
212 | } |
213 | |
214 | #[inline ] |
215 | fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target> { |
216 | SocketlikeView::new(self) |
217 | } |
218 | } |
219 | |
220 | /// A portable trait to borrow a reference from an underlying socketlike |
221 | /// object. |
222 | /// |
223 | /// This is a portability abstraction over Unix-like `AsFd` and Windows' |
224 | /// [`AsSocket`]. It also provides the `as_socketlike_view` convenience |
225 | /// function providing typed views. |
226 | #[cfg (windows)] |
227 | pub trait AsSocketlike: AsSocket { |
228 | /// Borrows the reference. |
229 | fn as_socketlike(&self) -> BorrowedSocketlike; |
230 | |
231 | /// Return a borrowing view of a resource which dereferences to a |
232 | /// `&Target`. |
233 | /// |
234 | /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some |
235 | /// cases, such as [`TcpStream`], `Read` and `Write` are implemented |
236 | /// for `&Target` in addition to `Target`, and you can get a `&mut |
237 | /// &Target` by doing `&*` on the resuting view, like this: |
238 | /// |
239 | /// ```rust,ignore |
240 | /// let v = s.as_socketlike_view::<std::net::TcpStream>(); |
241 | /// (&*v).read(&mut buf).unwrap(); |
242 | /// ``` |
243 | /// |
244 | /// [`TcpStream`]: std::net::TcpStream |
245 | fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>; |
246 | } |
247 | |
248 | #[cfg (windows)] |
249 | impl<T: AsSocket> AsSocketlike for T { |
250 | #[inline ] |
251 | fn as_socketlike(&self) -> BorrowedSocketlike<'_> { |
252 | self.as_socket() |
253 | } |
254 | |
255 | #[inline ] |
256 | fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target> { |
257 | SocketlikeView::new(self) |
258 | } |
259 | } |
260 | |
261 | /// A portable trait to express the ability to consume an object and acquire |
262 | /// ownership of its filelike object. |
263 | /// |
264 | /// This is a portability abstraction over Unix-like [`Into<OwnedFd>`] and |
265 | /// Windows' `Into<OwnedHandle>`. |
266 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
267 | pub trait IntoFilelike: Into<OwnedFd> { |
268 | /// Consumes this object, returning the underlying filelike object. |
269 | /// |
270 | /// # Example |
271 | /// |
272 | /// ```rust,no_run |
273 | /// use std::fs::File; |
274 | /// # use std::io; |
275 | /// use io_lifetimes::{IntoFilelike, OwnedFilelike}; |
276 | /// |
277 | /// let f = File::open("foo.txt" )?; |
278 | /// let owned_filelike: OwnedFilelike = f.into_filelike(); |
279 | /// # Ok::<(), io::Error>(()) |
280 | /// ``` |
281 | fn into_filelike(self) -> OwnedFilelike; |
282 | } |
283 | |
284 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
285 | impl<T: Into<OwnedFd>> IntoFilelike for T { |
286 | #[inline ] |
287 | fn into_filelike(self) -> OwnedFilelike { |
288 | self.into() |
289 | } |
290 | } |
291 | |
292 | /// A portable trait to express the ability to consume an object and acquire |
293 | /// ownership of its filelike object. |
294 | /// |
295 | /// This is a portability abstraction over Unix-like `Into<OwnedFd>` and |
296 | /// Windows' [`Into<OwnedHandle>`]. |
297 | #[cfg (windows)] |
298 | pub trait IntoFilelike: Into<OwnedHandle> { |
299 | /// Consumes this object, returning the underlying filelike object. |
300 | fn into_filelike(self) -> OwnedFilelike; |
301 | } |
302 | |
303 | #[cfg (windows)] |
304 | impl<T: Into<OwnedHandle>> IntoFilelike for T { |
305 | #[inline ] |
306 | fn into_filelike(self) -> OwnedFilelike { |
307 | self.into() |
308 | } |
309 | } |
310 | |
311 | /// A portable trait to express the ability to consume an object and acquire |
312 | /// ownership of its socketlike object. |
313 | /// |
314 | /// This is a portability abstraction over Unix-like [`Into<OwnedFd>`] and |
315 | /// Windows' `Into<OwnedSocket>`. |
316 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
317 | pub trait IntoSocketlike: Into<OwnedFd> { |
318 | /// Consumes this object, returning the underlying socketlike object. |
319 | fn into_socketlike(self) -> OwnedSocketlike; |
320 | } |
321 | |
322 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
323 | impl<T: Into<OwnedFd>> IntoSocketlike for T { |
324 | #[inline ] |
325 | fn into_socketlike(self) -> OwnedSocketlike { |
326 | self.into() |
327 | } |
328 | } |
329 | |
330 | /// A portable trait to express the ability to consume an object and acquire |
331 | /// ownership of its socketlike object. |
332 | /// |
333 | /// This is a portability abstraction over Unix-like `Into<OwnedFd>` and |
334 | /// Windows' [`Into<OwnedSocket>`]. |
335 | #[cfg (windows)] |
336 | pub trait IntoSocketlike: Into<OwnedSocket> { |
337 | /// Consumes this object, returning the underlying socketlike object. |
338 | /// |
339 | /// # Example |
340 | /// |
341 | /// ```rust,no_run |
342 | /// use std::fs::File; |
343 | /// # use std::io; |
344 | /// use io_lifetimes::{IntoFilelike, OwnedFilelike}; |
345 | /// |
346 | /// let f = File::open("foo.txt")?; |
347 | /// let owned_filelike: OwnedFilelike = f.into_filelike(); |
348 | /// # Ok::<(), io::Error>(()) |
349 | /// ``` |
350 | fn into_socketlike(self) -> OwnedSocketlike; |
351 | } |
352 | |
353 | #[cfg (windows)] |
354 | impl<T: Into<OwnedSocket>> IntoSocketlike for T { |
355 | #[inline ] |
356 | fn into_socketlike(self) -> OwnedSocketlike { |
357 | self.into() |
358 | } |
359 | } |
360 | |
361 | /// A portable trait to express the ability to construct an object from a |
362 | /// filelike object. |
363 | /// |
364 | /// This is a portability abstraction over Unix-like [`From<OwnedFd>`] and |
365 | /// Windows' `From<OwnedHandle>`. It also provides the `from_into_filelike` |
366 | /// convenience function providing simplified from+into conversions. |
367 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
368 | pub trait FromFilelike: From<OwnedFd> { |
369 | /// Constructs a new instance of `Self` from the given filelike object. |
370 | /// |
371 | /// # Example |
372 | /// |
373 | /// ```rust,no_run |
374 | /// use std::fs::File; |
375 | /// # use std::io; |
376 | /// use io_lifetimes::{FromFilelike, IntoFilelike, OwnedFilelike}; |
377 | /// |
378 | /// let f = File::open("foo.txt" )?; |
379 | /// let owned_filelike: OwnedFilelike = f.into_filelike(); |
380 | /// let f = File::from_filelike(owned_filelike); |
381 | /// # Ok::<(), io::Error>(()) |
382 | /// ``` |
383 | fn from_filelike(owned: OwnedFilelike) -> Self; |
384 | |
385 | /// Constructs a new instance of `Self` from the given filelike object |
386 | /// converted from `into_owned`. |
387 | /// |
388 | /// # Example |
389 | /// |
390 | /// ```rust,no_run |
391 | /// use std::fs::File; |
392 | /// # use std::io; |
393 | /// use io_lifetimes::{FromFilelike, IntoFilelike}; |
394 | /// |
395 | /// let f = File::open("foo.txt" )?; |
396 | /// let f = File::from_into_filelike(f); |
397 | /// # Ok::<(), io::Error>(()) |
398 | /// ``` |
399 | fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self; |
400 | } |
401 | |
402 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
403 | impl<T: From<OwnedFd>> FromFilelike for T { |
404 | #[inline ] |
405 | fn from_filelike(owned: OwnedFilelike) -> Self { |
406 | Self::from(owned) |
407 | } |
408 | |
409 | #[inline ] |
410 | fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self { |
411 | Self::from_filelike(owned:owned.into_filelike()) |
412 | } |
413 | } |
414 | |
415 | /// A portable trait to express the ability to construct an object from a |
416 | /// filelike object. |
417 | /// |
418 | /// This is a portability abstraction over Unix-like `From<OwnedFd>` and |
419 | /// Windows' [`From<OwnedHandle>`]. It also provides the `from_into_filelike` |
420 | /// convenience function providing simplified from+into conversions. |
421 | #[cfg (windows)] |
422 | pub trait FromFilelike: From<OwnedHandle> { |
423 | /// Constructs a new instance of `Self` from the given filelike object. |
424 | /// |
425 | /// # Example |
426 | /// |
427 | /// ```rust,no_run |
428 | /// use std::fs::File; |
429 | /// # use std::io; |
430 | /// use io_lifetimes::{FromFilelike, IntoFilelike, OwnedFilelike}; |
431 | /// |
432 | /// let f = File::open("foo.txt")?; |
433 | /// let owned_filelike: OwnedFilelike = f.into_filelike(); |
434 | /// let f = File::from_filelike(owned_filelike); |
435 | /// # Ok::<(), io::Error>(()) |
436 | /// ``` |
437 | fn from_filelike(owned: OwnedFilelike) -> Self; |
438 | |
439 | /// Constructs a new instance of `Self` from the given filelike object |
440 | /// converted from `into_owned`. |
441 | /// |
442 | /// # Example |
443 | /// |
444 | /// ```rust,no_run |
445 | /// use std::fs::File; |
446 | /// # use std::io; |
447 | /// use io_lifetimes::{FromFilelike, IntoFilelike}; |
448 | /// |
449 | /// let f = File::open("foo.txt")?; |
450 | /// let f = File::from_into_filelike(f); |
451 | /// # Ok::<(), io::Error>(()) |
452 | /// ``` |
453 | fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self; |
454 | } |
455 | |
456 | #[cfg (windows)] |
457 | impl<T: From<OwnedHandle>> FromFilelike for T { |
458 | #[inline ] |
459 | fn from_filelike(owned: OwnedFilelike) -> Self { |
460 | Self::from(owned) |
461 | } |
462 | |
463 | #[inline ] |
464 | fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self { |
465 | Self::from_filelike(owned.into_filelike()) |
466 | } |
467 | } |
468 | |
469 | /// A portable trait to express the ability to construct an object from a |
470 | /// socketlike object. |
471 | /// |
472 | /// This is a portability abstraction over Unix-like [`From<OwnedFd>`] and |
473 | /// Windows' `From<OwnedSocketFrom<OwnedSocket>` It also provides the |
474 | /// `from_into_socketlike` convenience function providing simplified from+into |
475 | /// conversions. |
476 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
477 | pub trait FromSocketlike: From<OwnedFd> { |
478 | /// Constructs a new instance of `Self` from the given socketlike object. |
479 | fn from_socketlike(owned: OwnedSocketlike) -> Self; |
480 | |
481 | /// Constructs a new instance of `Self` from the given socketlike object |
482 | /// converted from `into_owned`. |
483 | fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self; |
484 | } |
485 | |
486 | #[cfg (any(unix, target_os = "wasi" , target_os = "hermit" ))] |
487 | impl<T: From<OwnedFd>> FromSocketlike for T { |
488 | #[inline ] |
489 | fn from_socketlike(owned: OwnedSocketlike) -> Self { |
490 | Self::from(owned) |
491 | } |
492 | |
493 | #[inline ] |
494 | fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self { |
495 | Self::from_socketlike(owned:owned.into_socketlike()) |
496 | } |
497 | } |
498 | |
499 | /// A portable trait to express the ability to construct an object from a |
500 | /// socketlike object. |
501 | /// |
502 | /// This is a portability abstraction over Unix-like `From<OwnedFd>` and |
503 | /// Windows' [`From<OwnedSocket>`]. It also provides the `from_into_socketlike` |
504 | /// convenience function providing simplified from+into conversions. |
505 | #[cfg (windows)] |
506 | pub trait FromSocketlike: From<OwnedSocket> { |
507 | /// Constructs a new instance of `Self` from the given socketlike object. |
508 | fn from_socketlike(owned: OwnedSocketlike) -> Self; |
509 | |
510 | /// Constructs a new instance of `Self` from the given socketlike object |
511 | /// converted from `into_owned`. |
512 | fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self; |
513 | } |
514 | |
515 | #[cfg (windows)] |
516 | impl<T: From<OwnedSocket>> FromSocketlike for T { |
517 | #[inline ] |
518 | fn from_socketlike(owned: OwnedSocketlike) -> Self { |
519 | Self::from(owned) |
520 | } |
521 | |
522 | #[inline ] |
523 | fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self { |
524 | Self::from_socketlike(owned.into_socketlike()) |
525 | } |
526 | } |
527 | |