• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"))]
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"))]
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"))]
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"))]
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"))]
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"))]
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     /// ```
as_filelike(&self) -> BorrowedFilelike<'_>89     fn as_filelike(&self) -> BorrowedFilelike<'_>;
90 
91     /// Return a borrowing view of a resource which dereferences to a `&Target`.
92     ///
93     /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases,
94     /// such as [`File`], `Read` and `Write` are implemented for `&Target` in
95     /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on
96     /// the resuting view, like this:
97     ///
98     /// ```rust,ignore
99     /// let v = f.as_filelike_view::<std::fs::File>();
100     /// (&*v).read(&mut buf).unwrap();
101     /// ```
102     ///
103     /// [`File`]: std::fs::File
104     /// [`Read`]: std::io::Read
105     /// [`Write`]: std::io::Write
as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>106     fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>;
107 }
108 
109 #[cfg(any(unix, target_os = "wasi"))]
110 impl<T: AsFd> AsFilelike for T {
111     #[inline]
as_filelike(&self) -> BorrowedFilelike<'_>112     fn as_filelike(&self) -> BorrowedFilelike<'_> {
113         self.as_fd()
114     }
115 
116     #[inline]
as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>117     fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target> {
118         FilelikeView::new(self)
119     }
120 }
121 
122 /// A portable trait to borrow a reference from an underlying filelike object.
123 ///
124 /// This is a portability abstraction over Unix-like `AsFd` and Windows'
125 /// [`AsHandle`]. It also provides the `as_filelike_view` convenience function
126 /// providing typed views.
127 #[cfg(windows)]
128 pub trait AsFilelike: AsHandle {
129     /// Borrows the reference.
130     ///
131     /// # Example
132     ///
133     /// ```rust,no_run
134     /// use std::fs::File;
135     /// # use std::io;
136     /// use io_lifetimes::{AsFilelike, BorrowedFilelike};
137     ///
138     /// let mut f = File::open("foo.txt")?;
139     /// let borrowed_filelike: BorrowedFilelike<'_> = f.as_filelike();
140     /// # Ok::<(), io::Error>(())
141     /// ```
as_filelike(&self) -> BorrowedFilelike<'_>142     fn as_filelike(&self) -> BorrowedFilelike<'_>;
143 
144     /// Return a borrowing view of a resource which dereferences to a `&Target`.
145     ///
146     /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases,
147     /// such as [`File`], `Read` and `Write` are implemented for `&Target` in
148     /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on
149     /// the resuting view, like this:
150     ///
151     /// ```rust,ignore
152     /// let v = f.as_filelike_view::<std::fs::File>();
153     /// (&*v).read(&mut buf).unwrap();
154     /// ```
155     ///
156     /// [`File`]: std::fs::File
157     /// [`Read`]: std::io::Read
158     /// [`Write`]: std::io::Write
as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>159     fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>;
160 }
161 
162 #[cfg(windows)]
163 impl<T: AsHandle> AsFilelike for T {
164     #[inline]
as_filelike(&self) -> BorrowedFilelike<'_>165     fn as_filelike(&self) -> BorrowedFilelike<'_> {
166         self.as_handle()
167     }
168 
169     #[inline]
as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target>170     fn as_filelike_view<Target: FilelikeViewType>(&self) -> FilelikeView<'_, Target> {
171         FilelikeView::new(self)
172     }
173 }
174 
175 /// A portable trait to borrow a reference from an underlying socketlike
176 /// object.
177 ///
178 /// This is a portability abstraction over Unix-like [`AsFd`] and Windows'
179 /// `AsSocket`. It also provides the `as_socketlike_view` convenience
180 /// function providing typed views.
181 #[cfg(any(unix, target_os = "wasi"))]
182 pub trait AsSocketlike: AsFd {
183     /// Borrows the reference.
as_socketlike(&self) -> BorrowedSocketlike<'_>184     fn as_socketlike(&self) -> BorrowedSocketlike<'_>;
185 
186     /// Return a borrowing view of a resource which dereferences to a `&Target`.
187     ///
188     /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases,
189     /// such as [`TcpStream`], `Read` and `Write` are implemented for `&Target` in
190     /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on
191     /// the resuting view, like this:
192     ///
193     /// ```rust,ignore
194     /// let v = s.as_socketlike_view::<std::net::TcpStream>();
195     /// (&*v).read(&mut buf).unwrap();
196     /// ```
197     ///
198     /// [`TcpStream`]: std::net::TcpStream
199     /// [`Read`]: std::io::Read
200     /// [`Write`]: std::io::Write
as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>201     fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>;
202 }
203 
204 #[cfg(any(unix, target_os = "wasi"))]
205 impl<T: AsFd> AsSocketlike for T {
206     #[inline]
as_socketlike(&self) -> BorrowedSocketlike<'_>207     fn as_socketlike(&self) -> BorrowedSocketlike<'_> {
208         self.as_fd()
209     }
210 
211     #[inline]
as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>212     fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target> {
213         SocketlikeView::new(self)
214     }
215 }
216 
217 /// A portable trait to borrow a reference from an underlying socketlike
218 /// object.
219 ///
220 /// This is a portability abstraction over Unix-like `AsFd` and Windows'
221 /// [`AsSocket`]. It also provides the `as_socketlike_view` convenience
222 /// function providing typed views.
223 #[cfg(windows)]
224 pub trait AsSocketlike: AsSocket {
225     /// Borrows the reference.
as_socketlike(&self) -> BorrowedSocketlike226     fn as_socketlike(&self) -> BorrowedSocketlike;
227 
228     /// Return a borrowing view of a resource which dereferences to a `&Target`.
229     ///
230     /// Note that [`Read`] or [`Write`] require `&mut Target`, but in some cases,
231     /// such as [`TcpStream`], `Read` and `Write` are implemented for `&Target` in
232     /// addition to `Target`, and you can get a `&mut &Target` by doing `&*` on
233     /// the resuting view, like this:
234     ///
235     /// ```rust,ignore
236     /// let v = s.as_socketlike_view::<std::net::TcpStream>();
237     /// (&*v).read(&mut buf).unwrap();
238     /// ```
239     ///
240     /// [`TcpStream`]: std::net::TcpStream
as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>241     fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>;
242 }
243 
244 #[cfg(windows)]
245 impl<T: AsSocket> AsSocketlike for T {
246     #[inline]
as_socketlike(&self) -> BorrowedSocketlike<'_>247     fn as_socketlike(&self) -> BorrowedSocketlike<'_> {
248         self.as_socket()
249     }
250 
251     #[inline]
as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target>252     fn as_socketlike_view<Target: SocketlikeViewType>(&self) -> SocketlikeView<'_, Target> {
253         SocketlikeView::new(self)
254     }
255 }
256 
257 /// A portable trait to express the ability to consume an object and acquire
258 /// ownership of its filelike object.
259 ///
260 /// This is a portability abstraction over Unix-like [`Into<OwnedFd>`] and Windows'
261 /// `Into<OwnedHandle>`.
262 #[cfg(any(unix, target_os = "wasi"))]
263 pub trait IntoFilelike: Into<OwnedFd> {
264     /// Consumes this object, returning the underlying filelike object.
265     ///
266     /// # Example
267     ///
268     /// ```rust,no_run
269     /// use std::fs::File;
270     /// # use std::io;
271     /// use io_lifetimes::{IntoFilelike, OwnedFilelike};
272     ///
273     /// let f = File::open("foo.txt")?;
274     /// let owned_filelike: OwnedFilelike = f.into_filelike();
275     /// # Ok::<(), io::Error>(())
276     /// ```
into_filelike(self) -> OwnedFilelike277     fn into_filelike(self) -> OwnedFilelike;
278 }
279 
280 #[cfg(any(unix, target_os = "wasi"))]
281 impl<T: Into<OwnedFd>> IntoFilelike for T {
282     #[inline]
into_filelike(self) -> OwnedFilelike283     fn into_filelike(self) -> OwnedFilelike {
284         self.into()
285     }
286 }
287 
288 /// A portable trait to express the ability to consume an object and acquire
289 /// ownership of its filelike object.
290 ///
291 /// This is a portability abstraction over Unix-like `Into<OwnedFd>` and Windows'
292 /// [`Into<OwnedHandle>`].
293 #[cfg(windows)]
294 pub trait IntoFilelike: Into<OwnedHandle> {
295     /// Consumes this object, returning the underlying filelike object.
into_filelike(self) -> OwnedFilelike296     fn into_filelike(self) -> OwnedFilelike;
297 }
298 
299 #[cfg(windows)]
300 impl<T: Into<OwnedHandle>> IntoFilelike for T {
301     #[inline]
into_filelike(self) -> OwnedFilelike302     fn into_filelike(self) -> OwnedFilelike {
303         self.into()
304     }
305 }
306 
307 /// A portable trait to express the ability to consume an object and acquire
308 /// ownership of its socketlike object.
309 ///
310 /// This is a portability abstraction over Unix-like [`Into<OwnedFd>`] and Windows'
311 /// `Into<OwnedSocket>`.
312 #[cfg(any(unix, target_os = "wasi"))]
313 pub trait IntoSocketlike: Into<OwnedFd> {
314     /// Consumes this object, returning the underlying socketlike object.
into_socketlike(self) -> OwnedSocketlike315     fn into_socketlike(self) -> OwnedSocketlike;
316 }
317 
318 #[cfg(any(unix, target_os = "wasi"))]
319 impl<T: Into<OwnedFd>> IntoSocketlike for T {
320     #[inline]
into_socketlike(self) -> OwnedSocketlike321     fn into_socketlike(self) -> OwnedSocketlike {
322         self.into()
323     }
324 }
325 
326 /// A portable trait to express the ability to consume an object and acquire
327 /// ownership of its socketlike object.
328 ///
329 /// This is a portability abstraction over Unix-like `Into<OwnedFd>` and Windows'
330 /// [`Into<OwnedSocket>`].
331 #[cfg(windows)]
332 pub trait IntoSocketlike: Into<OwnedSocket> {
333     /// Consumes this object, returning the underlying socketlike object.
334     ///
335     /// # Example
336     ///
337     /// ```rust,no_run
338     /// use std::fs::File;
339     /// # use std::io;
340     /// use io_lifetimes::{IntoFilelike, OwnedFilelike};
341     ///
342     /// let f = File::open("foo.txt")?;
343     /// let owned_filelike: OwnedFilelike = f.into_filelike();
344     /// # Ok::<(), io::Error>(())
345     /// ```
into_socketlike(self) -> OwnedSocketlike346     fn into_socketlike(self) -> OwnedSocketlike;
347 }
348 
349 #[cfg(windows)]
350 impl<T: Into<OwnedSocket>> IntoSocketlike for T {
351     #[inline]
into_socketlike(self) -> OwnedSocketlike352     fn into_socketlike(self) -> OwnedSocketlike {
353         self.into()
354     }
355 }
356 
357 /// A portable trait to express the ability to construct an object from a
358 /// filelike object.
359 ///
360 /// This is a portability abstraction over Unix-like [`From<OwnedFd>`] and Windows'
361 /// `From<OwnedHandle>`. It also provides the `from_into_filelike` convenience
362 /// function providing simplified from+into conversions.
363 #[cfg(any(unix, target_os = "wasi"))]
364 pub trait FromFilelike: From<OwnedFd> {
365     /// Constructs a new instance of `Self` from the given filelike object.
366     ///
367     /// # Example
368     ///
369     /// ```rust,no_run
370     /// use std::fs::File;
371     /// # use std::io;
372     /// use io_lifetimes::{FromFilelike, IntoFilelike, OwnedFilelike};
373     ///
374     /// let f = File::open("foo.txt")?;
375     /// let owned_filelike: OwnedFilelike = f.into_filelike();
376     /// let f = File::from_filelike(owned_filelike);
377     /// # Ok::<(), io::Error>(())
378     /// ```
from_filelike(owned: OwnedFilelike) -> Self379     fn from_filelike(owned: OwnedFilelike) -> Self;
380 
381     /// Constructs a new instance of `Self` from the given filelike object
382     /// converted from `into_owned`.
383     ///
384     /// # Example
385     ///
386     /// ```rust,no_run
387     /// use std::fs::File;
388     /// # use std::io;
389     /// use io_lifetimes::{FromFilelike, IntoFilelike};
390     ///
391     /// let f = File::open("foo.txt")?;
392     /// let f = File::from_into_filelike(f);
393     /// # Ok::<(), io::Error>(())
394     /// ```
from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self395     fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self;
396 }
397 
398 #[cfg(any(unix, target_os = "wasi"))]
399 impl<T: From<OwnedFd>> FromFilelike for T {
400     #[inline]
from_filelike(owned: OwnedFilelike) -> Self401     fn from_filelike(owned: OwnedFilelike) -> Self {
402         Self::from(owned)
403     }
404 
405     #[inline]
from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self406     fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self {
407         Self::from_filelike(owned.into_filelike())
408     }
409 }
410 
411 /// A portable trait to express the ability to construct an object from a
412 /// filelike object.
413 ///
414 /// This is a portability abstraction over Unix-like `From<OwnedFd>` and Windows'
415 /// [`From<OwnedHandle>`]. It also provides the `from_into_filelike` convenience
416 /// function providing simplified from+into conversions.
417 #[cfg(windows)]
418 pub trait FromFilelike: From<OwnedHandle> {
419     /// Constructs a new instance of `Self` from the given filelike object.
420     ///
421     /// # Example
422     ///
423     /// ```rust,no_run
424     /// use std::fs::File;
425     /// # use std::io;
426     /// use io_lifetimes::{FromFilelike, IntoFilelike, OwnedFilelike};
427     ///
428     /// let f = File::open("foo.txt")?;
429     /// let owned_filelike: OwnedFilelike = f.into_filelike();
430     /// let f = File::from_filelike(owned_filelike);
431     /// # Ok::<(), io::Error>(())
432     /// ```
from_filelike(owned: OwnedFilelike) -> Self433     fn from_filelike(owned: OwnedFilelike) -> Self;
434 
435     /// Constructs a new instance of `Self` from the given filelike object
436     /// converted from `into_owned`.
437     ///
438     /// # Example
439     ///
440     /// ```rust,no_run
441     /// use std::fs::File;
442     /// # use std::io;
443     /// use io_lifetimes::{FromFilelike, IntoFilelike};
444     ///
445     /// let f = File::open("foo.txt")?;
446     /// let f = File::from_into_filelike(f);
447     /// # Ok::<(), io::Error>(())
448     /// ```
from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self449     fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self;
450 }
451 
452 #[cfg(windows)]
453 impl<T: From<OwnedHandle>> FromFilelike for T {
454     #[inline]
from_filelike(owned: OwnedFilelike) -> Self455     fn from_filelike(owned: OwnedFilelike) -> Self {
456         Self::from(owned)
457     }
458 
459     #[inline]
from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self460     fn from_into_filelike<Owned: IntoFilelike>(owned: Owned) -> Self {
461         Self::from_filelike(owned.into_filelike())
462     }
463 }
464 
465 /// A portable trait to express the ability to construct an object from a
466 /// socketlike object.
467 ///
468 /// This is a portability abstraction over Unix-like [`From<OwnedFd>`] and Windows'
469 /// `From<OwnedSocketFrom<OwnedSocket> It also provides the `from_into_socketlike` convenience
470 /// function providing simplified from+into conversions.
471 #[cfg(any(unix, target_os = "wasi"))]
472 pub trait FromSocketlike: From<OwnedFd> {
473     /// Constructs a new instance of `Self` from the given socketlike object.
from_socketlike(owned: OwnedSocketlike) -> Self474     fn from_socketlike(owned: OwnedSocketlike) -> Self;
475 
476     /// Constructs a new instance of `Self` from the given socketlike object
477     /// converted from `into_owned`.
from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self478     fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self;
479 }
480 
481 #[cfg(any(unix, target_os = "wasi"))]
482 impl<T: From<OwnedFd>> FromSocketlike for T {
483     #[inline]
from_socketlike(owned: OwnedSocketlike) -> Self484     fn from_socketlike(owned: OwnedSocketlike) -> Self {
485         Self::from(owned)
486     }
487 
488     #[inline]
from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self489     fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self {
490         Self::from_socketlike(owned.into_socketlike())
491     }
492 }
493 
494 /// A portable trait to express the ability to construct an object from a
495 /// socketlike object.
496 ///
497 /// This is a portability abstraction over Unix-like `From<OwnedFd>` and Windows'
498 /// [`From<OwnedSocket>`]. It also provides the `from_into_socketlike` convenience
499 /// function providing simplified from+into conversions.
500 #[cfg(windows)]
501 pub trait FromSocketlike: From<OwnedSocket> {
502     /// Constructs a new instance of `Self` from the given socketlike object.
from_socketlike(owned: OwnedSocketlike) -> Self503     fn from_socketlike(owned: OwnedSocketlike) -> Self;
504 
505     /// Constructs a new instance of `Self` from the given socketlike object
506     /// converted from `into_owned`.
from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self507     fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self;
508 }
509 
510 #[cfg(windows)]
511 impl<T: From<OwnedSocket>> FromSocketlike for T {
512     #[inline]
from_socketlike(owned: OwnedSocketlike) -> Self513     fn from_socketlike(owned: OwnedSocketlike) -> Self {
514         Self::from(owned)
515     }
516 
517     #[inline]
from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self518     fn from_into_socketlike<Owned: IntoSocketlike>(owned: Owned) -> Self {
519         Self::from_socketlike(owned.into_socketlike())
520     }
521 }
522