1//! Portability abstractions over `Raw*`.
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#[cfg(unix)]
8use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
9#[cfg(target_os = "wasi")]
10use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
11#[cfg(windows)]
12use std::os::windows::io::{
13    AsRawHandle, AsRawSocket, FromRawHandle, FromRawSocket, IntoRawHandle, IntoRawSocket,
14    RawHandle, RawSocket,
15};
16
17/// A raw filelike object.
18///
19/// This is a portability abstraction over Unix-like [`RawFd`] and
20/// Windows' `RawHandle`.
21#[cfg(any(unix, target_os = "wasi"))]
22pub type RawFilelike = RawFd;
23
24/// A raw filelike object.
25///
26/// This is a portability abstraction over Unix-like `RawFd` and
27/// Windows' [`RawHandle`].
28#[cfg(windows)]
29pub type RawFilelike = RawHandle;
30
31/// A raw socketlike object.
32///
33/// This is a portability abstraction over Unix-like [`RawFd`] and
34/// Windows' `RawSocket`.
35#[cfg(any(unix, target_os = "wasi"))]
36pub type RawSocketlike = RawFd;
37
38/// A raw socketlike object.
39///
40/// This is a portability abstraction over Unix-like `RawFd` and
41/// Windows' [`RawSocket`].
42#[cfg(windows)]
43pub type RawSocketlike = RawSocket;
44
45/// A portable trait to obtain the raw value of an underlying filelike object.
46///
47/// This is a portability abstraction over Unix-like [`AsRawFd`] and Windows'
48/// `AsRawHandle`.
49#[cfg(any(unix, target_os = "wasi"))]
50pub trait AsRawFilelike: AsRawFd {
51    /// Returns the raw value.
52    fn as_raw_filelike(&self) -> RawFilelike;
53}
54
55#[cfg(any(unix, target_os = "wasi"))]
56impl<T: AsRawFd> AsRawFilelike for T {
57    #[inline]
58    fn as_raw_filelike(&self) -> RawFilelike {
59        self.as_raw_fd()
60    }
61}
62
63/// This is a portability abstraction over Unix-like `AsRawFd` and Windows'
64/// [`AsRawHandle`].
65#[cfg(windows)]
66pub trait AsRawFilelike: AsRawHandle {
67    /// Returns the raw value.
68    fn as_raw_filelike(&self) -> RawFilelike;
69}
70
71#[cfg(windows)]
72impl<T: AsRawHandle> AsRawFilelike for T {
73    #[inline]
74    fn as_raw_filelike(&self) -> RawFilelike {
75        self.as_raw_handle()
76    }
77}
78
79/// This is a portability abstraction over Unix-like [`AsRawFd`] and Windows'
80/// `AsRawSocket`.
81#[cfg(any(unix, target_os = "wasi"))]
82pub trait AsRawSocketlike: AsRawFd {
83    /// Returns the raw value.
84    fn as_raw_socketlike(&self) -> RawSocketlike;
85}
86
87#[cfg(any(unix, target_os = "wasi"))]
88impl<T: AsRawFd> AsRawSocketlike for T {
89    #[inline]
90    fn as_raw_socketlike(&self) -> RawSocketlike {
91        self.as_raw_fd()
92    }
93}
94
95/// This is a portability abstraction over Unix-like `AsRawFd` and Windows'
96/// [`AsRawSocket`].
97#[cfg(windows)]
98pub trait AsRawSocketlike: AsRawSocket {
99    /// Returns the raw value.
100    fn as_raw_socketlike(&self) -> RawSocketlike;
101}
102
103#[cfg(windows)]
104impl<T: AsRawSocket> AsRawSocketlike for T {
105    #[inline]
106    fn as_raw_socketlike(&self) -> RawSocketlike {
107        self.as_raw_socket()
108    }
109}
110
111/// This is a portability abstraction over Unix-like [`IntoRawFd`] and Windows'
112/// `IntoRawHandle`.
113#[cfg(any(unix, target_os = "wasi"))]
114pub trait IntoRawFilelike: IntoRawFd {
115    /// Returns the raw value.
116    fn into_raw_filelike(self) -> RawFilelike;
117}
118
119#[cfg(any(unix, target_os = "wasi"))]
120impl<T: IntoRawFd> IntoRawFilelike for T {
121    #[inline]
122    fn into_raw_filelike(self) -> RawFilelike {
123        self.into_raw_fd()
124    }
125}
126
127/// This is a portability abstraction over Unix-like `IntoRawFd` and Windows'
128/// [`IntoRawHandle`].
129#[cfg(windows)]
130pub trait IntoRawFilelike: IntoRawHandle {
131    /// Returns the raw value.
132    fn into_raw_filelike(self) -> RawFilelike;
133}
134
135#[cfg(windows)]
136impl<T: IntoRawHandle> IntoRawFilelike for T {
137    #[inline]
138    fn into_raw_filelike(self) -> RawFilelike {
139        self.into_raw_handle()
140    }
141}
142
143/// This is a portability abstraction over Unix-like [`IntoRawFd`] and Windows'
144/// `IntoRawSocket`.
145#[cfg(any(unix, target_os = "wasi"))]
146pub trait IntoRawSocketlike: IntoRawFd {
147    /// Returns the raw value.
148    fn into_raw_socketlike(self) -> RawSocketlike;
149}
150
151#[cfg(any(unix, target_os = "wasi"))]
152impl<T: IntoRawFd> IntoRawSocketlike for T {
153    #[inline]
154    fn into_raw_socketlike(self) -> RawSocketlike {
155        self.into_raw_fd()
156    }
157}
158
159/// This is a portability abstraction over Unix-like `IntoRawFd` and Windows'
160/// [`IntoRawSocket`].
161#[cfg(windows)]
162pub trait IntoRawSocketlike: IntoRawSocket {
163    /// Returns the raw value.
164    fn into_raw_socketlike(self) -> RawSocketlike;
165}
166
167#[cfg(windows)]
168impl<T: IntoRawSocket> IntoRawSocketlike for T {
169    #[inline]
170    fn into_raw_socketlike(self) -> RawSocketlike {
171        self.into_raw_socket()
172    }
173}
174
175/// This is a portability abstraction over Unix-like [`FromRawFd`] and Windows'
176/// `FromRawHandle`.
177#[cfg(any(unix, target_os = "wasi"))]
178pub trait FromRawFilelike: FromRawFd {
179    /// Constructs `Self` from the raw value.
180    ///
181    /// # Safety
182    ///
183    /// This is `unsafe` for the same reason as [`from_raw_fd`] and
184    /// [`from_raw_handle`].
185    ///
186    /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.from_raw_fd
187    /// [`from_raw_handle`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.FromRawHandle.html#tymethod.from_raw_handle
188    unsafe fn from_raw_filelike(raw: RawFilelike) -> Self;
189}
190
191#[cfg(any(unix, target_os = "wasi"))]
192impl<T: FromRawFd> FromRawFilelike for T {
193    #[inline]
194    unsafe fn from_raw_filelike(raw: RawFilelike) -> Self {
195        Self::from_raw_fd(raw)
196    }
197}
198
199/// This is a portability abstraction over Unix-like `FromRawFd` and Windows'
200/// [`FromRawHandle`].
201#[cfg(windows)]
202pub trait FromRawFilelike: FromRawHandle {
203    /// Constructs `Self` from the raw value.
204    unsafe fn from_raw_filelike(raw: RawFilelike) -> Self;
205}
206
207#[cfg(windows)]
208impl<T: FromRawHandle> FromRawFilelike for T {
209    #[inline]
210    unsafe fn from_raw_filelike(raw: RawFilelike) -> Self {
211        Self::from_raw_handle(raw)
212    }
213}
214
215/// This is a portability abstraction over Unix-like [`FromRawFd`] and Windows'
216/// `FromRawSocket`.
217#[cfg(any(unix, target_os = "wasi"))]
218pub trait FromRawSocketlike: FromRawFd {
219    /// Constructs `Self` from the raw value.
220    ///
221    /// # Safety
222    ///
223    /// This is `unsafe` for the same reason as [`from_raw_fd`] and
224    /// [`from_raw_socket`].
225    ///
226    /// [`from_raw_fd`]: https://doc.rust-lang.org/stable/std/os/unix/io/trait.FromRawFd.html#tymethod.from_raw_fd
227    /// [`from_raw_socket`]: https://doc.rust-lang.org/stable/std/os/windows/io/trait.FromRawSocket.html#tymethod.from_raw_socket
228    unsafe fn from_raw_socketlike(raw: RawSocketlike) -> Self;
229}
230
231#[cfg(any(unix, target_os = "wasi"))]
232impl<T: FromRawFd> FromRawSocketlike for T {
233    #[inline]
234    unsafe fn from_raw_socketlike(raw: RawSocketlike) -> Self {
235        Self::from_raw_fd(raw)
236    }
237}
238
239/// This is a portability abstraction over Unix-like `FromRawFd` and Windows'
240/// [`FromRawSocket`].
241#[cfg(windows)]
242pub trait FromRawSocketlike: FromRawSocket {
243    /// Constructs `Self` from the raw value.
244    unsafe fn from_raw_socketlike(raw: RawSocketlike) -> Self;
245}
246
247#[cfg(windows)]
248impl<T: FromRawSocket> FromRawSocketlike for T {
249    #[inline]
250    unsafe fn from_raw_socketlike(raw: RawSocketlike) -> Self {
251        Self::from_raw_socket(raw)
252    }
253}
254