io_extras/
raw.rs

1//! `RawReadable` and `RawWriteable`.
2
3use crate::grip::RawGrip;
4#[cfg(not(windows))]
5use crate::os::rustix::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
6use io_lifetimes::raw::RawFilelike;
7use io_lifetimes::views::FilelikeView;
8use std::fmt;
9use std::fs::File;
10use std::io::{self, IoSlice, IoSliceMut, Read, Write};
11#[cfg(all(doc, not(windows)))]
12use std::net::TcpStream;
13#[cfg(windows)]
14use {
15    crate::os::windows::{
16        AsRawHandleOrSocket, FromRawHandleOrSocket, IntoRawHandleOrSocket, RawEnum,
17        RawHandleOrSocket,
18    },
19    io_lifetimes::raw::RawSocketlike,
20    io_lifetimes::views::SocketlikeView,
21    std::net::TcpStream,
22    std::os::windows::io::{FromRawHandle, RawHandle},
23};
24
25/// A non-owning unsafe I/O handle that implements [`Read`]. `Read` functions
26/// are considered safe, so this type requires `unsafe` to construct.
27///
28/// This doesn't implement `Into*` or `From*` traits.
29///
30/// # Platform-specific behavior
31///
32/// On Posix-ish platforms, this reads from the handle as if it were a
33/// [`File`]. On Windows, this reads from a file-like handle as if it were a
34/// [`File`], and from a socket-like handle as if it were a [`TcpStream`].
35#[derive(Copy, Clone)]
36#[repr(transparent)]
37pub struct RawReadable(RawGrip);
38
39/// A non-owning unsafe I/O handle that implements [`Write`]. `Write` functions
40/// considered are safe, so this type requires `unsafe` to construct.
41///
42/// This doesn't implement `Into*` or `From*` traits.
43///
44/// # Platform-specific behavior
45///
46/// On Posix-ish platforms, this writes to the handle as if it were a
47/// [`File`]. On Windows, this writes to a file-like handle as if it were a
48/// [`File`], and to a socket-like handle as if it were a [`TcpStream`].
49#[derive(Copy, Clone)]
50#[repr(transparent)]
51pub struct RawWriteable(RawGrip);
52
53/// `RawReadable` doesn't own its handle.
54#[cfg(not(windows))]
55impl AsRawFd for RawReadable {
56    #[inline]
57    fn as_raw_fd(&self) -> RawFd {
58        self.0
59    }
60}
61
62/// `RawReadable` doesn't own its handle.
63#[cfg(not(windows))]
64impl IntoRawFd for RawReadable {
65    #[inline]
66    fn into_raw_fd(self) -> RawFd {
67        self.0
68    }
69}
70
71/// `RawReadable` doesn't own its handle.
72#[cfg(not(windows))]
73impl FromRawFd for RawReadable {
74    #[inline]
75    unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
76        Self(raw_fd)
77    }
78}
79
80/// `RawWriteable` doesn't own its handle.
81#[cfg(not(windows))]
82impl AsRawFd for RawWriteable {
83    #[inline]
84    fn as_raw_fd(&self) -> RawFd {
85        self.0
86    }
87}
88
89/// `RawWriteable` doesn't own its handle.
90#[cfg(not(windows))]
91impl IntoRawFd for RawWriteable {
92    #[inline]
93    fn into_raw_fd(self) -> RawFd {
94        self.0
95    }
96}
97
98/// `RawWriteable` doesn't own its handle.
99#[cfg(not(windows))]
100impl FromRawFd for RawWriteable {
101    #[inline]
102    unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
103        Self(raw_fd)
104    }
105}
106
107// Windows implementations.
108
109/// `RawReadable` doesn't own its handle.
110#[cfg(windows)]
111impl AsRawHandleOrSocket for RawReadable {
112    #[inline]
113    fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
114        self.0
115    }
116}
117
118/// `RawReadable` doesn't own its handle.
119#[cfg(windows)]
120impl IntoRawHandleOrSocket for RawReadable {
121    #[inline]
122    fn into_raw_handle_or_socket(self) -> RawHandleOrSocket {
123        self.0
124    }
125}
126
127/// `RawReadable` doesn't own its handle.
128#[cfg(windows)]
129impl FromRawHandleOrSocket for RawReadable {
130    #[inline]
131    unsafe fn from_raw_handle_or_socket(raw_handle_or_socket: RawHandleOrSocket) -> Self {
132        Self(raw_handle_or_socket)
133    }
134}
135
136/// `RawReadable` doesn't own its handle.
137#[cfg(windows)]
138impl FromRawHandle for RawReadable {
139    #[inline]
140    unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
141        Self(RawHandleOrSocket::unowned_from_raw_handle(raw_handle))
142    }
143}
144
145/// `RawWriteable` doesn't own its handle.
146#[cfg(windows)]
147impl AsRawHandleOrSocket for RawWriteable {
148    #[inline]
149    fn as_raw_handle_or_socket(&self) -> RawHandleOrSocket {
150        self.0
151    }
152}
153
154/// `RawWriteable` doesn't own its handle.
155#[cfg(windows)]
156impl IntoRawHandleOrSocket for RawWriteable {
157    #[inline]
158    fn into_raw_handle_or_socket(self) -> RawHandleOrSocket {
159        self.0
160    }
161}
162
163/// `RawWriteable` doesn't own its handle.
164#[cfg(windows)]
165impl FromRawHandleOrSocket for RawWriteable {
166    #[inline]
167    unsafe fn from_raw_handle_or_socket(raw_handle_or_socket: RawHandleOrSocket) -> Self {
168        Self(raw_handle_or_socket)
169    }
170}
171
172/// `RawWriteable` doesn't own its handle.
173#[cfg(windows)]
174impl FromRawHandle for RawWriteable {
175    #[inline]
176    unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
177        Self(RawHandleOrSocket::unowned_from_raw_handle(raw_handle))
178    }
179}
180
181#[inline]
182unsafe fn as_file_view<'a>(file: RawFilelike) -> FilelikeView<'a, File> {
183    FilelikeView::<'a>::view_raw(file)
184}
185
186#[cfg(windows)]
187#[inline]
188unsafe fn as_socket_view<'a>(socket: RawSocketlike) -> SocketlikeView<'a, TcpStream> {
189    SocketlikeView::<'a>::view_raw(socket)
190}
191
192#[cfg(not(windows))]
193impl Read for RawReadable {
194    #[inline]
195    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
196        // Safety: The caller of `as_readable()`, which is unsafe, is expected
197        // to ensure that the underlying resource outlives this
198        // `RawReadable`.
199        unsafe { &*as_file_view(self.0) }.read(buf)
200    }
201
202    #[inline]
203    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
204        unsafe { &*as_file_view(self.0) }.read_vectored(bufs)
205    }
206
207    #[cfg(can_vector)]
208    #[inline]
209    fn is_read_vectored(&self) -> bool {
210        unsafe { &*as_file_view(self.0) }.is_read_vectored()
211    }
212
213    #[inline]
214    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
215        unsafe { &*as_file_view(self.0) }.read_to_end(buf)
216    }
217
218    #[inline]
219    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
220        unsafe { &*as_file_view(self.0) }.read_to_string(buf)
221    }
222
223    #[inline]
224    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
225        unsafe { &*as_file_view(self.0) }.read_exact(buf)
226    }
227}
228
229#[cfg(windows)]
230impl Read for RawReadable {
231    #[inline]
232    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
233        match self.0 .0 {
234            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.read(buf),
235            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.read(buf),
236            RawEnum::Stdio(ref mut stdio) => stdio.read(buf),
237        }
238    }
239
240    #[inline]
241    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
242        match self.0 .0 {
243            RawEnum::Handle(raw_handle) => {
244                unsafe { &*as_file_view(raw_handle) }.read_vectored(bufs)
245            }
246            RawEnum::Socket(raw_socket) => {
247                unsafe { &*as_socket_view(raw_socket) }.read_vectored(bufs)
248            }
249            RawEnum::Stdio(ref mut stdio) => stdio.read_vectored(bufs),
250        }
251    }
252
253    #[cfg(can_vector)]
254    #[inline]
255    fn is_read_vectored(&self) -> bool {
256        match self.0 .0 {
257            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.is_read_vectored(),
258            RawEnum::Socket(raw_socket) => {
259                unsafe { &*as_socket_view(raw_socket) }.is_read_vectored()
260            }
261            RawEnum::Stdio(ref stdio) => stdio.is_read_vectored(),
262        }
263    }
264
265    #[inline]
266    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
267        match self.0 .0 {
268            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.read_to_end(buf),
269            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.read_to_end(buf),
270            RawEnum::Stdio(ref mut stdio) => stdio.read_to_end(buf),
271        }
272    }
273
274    #[inline]
275    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
276        match self.0 .0 {
277            RawEnum::Handle(raw_handle) => {
278                unsafe { &*as_file_view(raw_handle) }.read_to_string(buf)
279            }
280            RawEnum::Socket(raw_socket) => {
281                unsafe { &*as_socket_view(raw_socket) }.read_to_string(buf)
282            }
283            RawEnum::Stdio(ref mut stdio) => stdio.read_to_string(buf),
284        }
285    }
286
287    #[inline]
288    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
289        match self.0 .0 {
290            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.read_exact(buf),
291            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.read_exact(buf),
292            RawEnum::Stdio(ref mut stdio) => stdio.read_exact(buf),
293        }
294    }
295}
296
297#[cfg(not(windows))]
298impl Write for RawWriteable {
299    #[inline]
300    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
301        // Safety: The caller of `as_writeable()`, which is unsafe, is expected
302        // to ensure that the underlying resource outlives this
303        // `RawReadable`.
304        unsafe { &*as_file_view(self.0) }.write(buf)
305    }
306
307    #[inline]
308    fn flush(&mut self) -> io::Result<()> {
309        unsafe { &*as_file_view(self.0) }.flush()
310    }
311
312    #[inline]
313    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
314        unsafe { &*as_file_view(self.0) }.write_vectored(bufs)
315    }
316
317    #[cfg(can_vector)]
318    #[inline]
319    fn is_write_vectored(&self) -> bool {
320        unsafe { &*as_file_view(self.0) }.is_write_vectored()
321    }
322
323    #[inline]
324    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
325        unsafe { &*as_file_view(self.0) }.write_all(buf)
326    }
327
328    #[cfg(write_all_vectored)]
329    #[inline]
330    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
331        unsafe { &*as_file_view(self.0) }.write_all_vectored(bufs)
332    }
333
334    #[inline]
335    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
336        unsafe { &*as_file_view(self.0) }.write_fmt(fmt)
337    }
338}
339
340#[cfg(windows)]
341impl Write for RawWriteable {
342    #[inline]
343    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
344        match self.0 .0 {
345            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.write(buf),
346            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.write(buf),
347            RawEnum::Stdio(ref mut stdio) => stdio.write(buf),
348        }
349    }
350
351    #[inline]
352    fn flush(&mut self) -> io::Result<()> {
353        match self.0 .0 {
354            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.flush(),
355            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.flush(),
356            RawEnum::Stdio(ref mut stdio) => stdio.flush(),
357        }
358    }
359
360    #[inline]
361    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
362        match self.0 .0 {
363            RawEnum::Handle(raw_handle) => {
364                unsafe { &*as_file_view(raw_handle) }.write_vectored(bufs)
365            }
366            RawEnum::Socket(raw_socket) => {
367                unsafe { &*as_socket_view(raw_socket) }.write_vectored(bufs)
368            }
369            RawEnum::Stdio(ref mut stdio) => stdio.write_vectored(bufs),
370        }
371    }
372
373    #[cfg(can_vector)]
374    #[inline]
375    fn is_write_vectored(&self) -> bool {
376        match self.0 .0 {
377            RawEnum::Handle(raw_handle) => {
378                unsafe { &*as_file_view(raw_handle) }.is_write_vectored()
379            }
380            RawEnum::Socket(raw_socket) => {
381                unsafe { &*as_socket_view(raw_socket) }.is_write_vectored()
382            }
383            RawEnum::Stdio(ref stdio) => stdio.is_write_vectored(),
384        }
385    }
386
387    #[inline]
388    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
389        match self.0 .0 {
390            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.write_all(buf),
391            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.write_all(buf),
392            RawEnum::Stdio(ref mut stdio) => stdio.write_all(buf),
393        }
394    }
395
396    #[cfg(write_all_vectored)]
397    #[inline]
398    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
399        match self.0 .0 {
400            RawEnum::Handle(raw_handle) => {
401                unsafe { &*as_file_view(raw_handle) }.write_all_vectored(bufs)
402            }
403            RawEnum::Socket(raw_socket) => {
404                unsafe { &*as_socket_view(raw_socket) }.write_all_vectored(bufs)
405            }
406            RawEnum::Stdio(ref mut stdio) => stdio.write_all_vectored(bufs),
407        }
408    }
409
410    #[inline]
411    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
412        match self.0 .0 {
413            RawEnum::Handle(raw_handle) => unsafe { &*as_file_view(raw_handle) }.write_fmt(fmt),
414            RawEnum::Socket(raw_socket) => unsafe { &*as_socket_view(raw_socket) }.write_fmt(fmt),
415            RawEnum::Stdio(ref mut stdio) => stdio.write_fmt(fmt),
416        }
417    }
418}
419
420#[cfg(not(windows))]
421impl fmt::Debug for RawReadable {
422    #[allow(clippy::missing_inline_in_public_items)]
423    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
424        // Just print the raw fd number.
425        f.debug_struct("RawReadable")
426            .field("raw_fd", &self.0)
427            .finish()
428    }
429}
430
431#[cfg(windows)]
432impl fmt::Debug for RawReadable {
433    #[allow(clippy::missing_inline_in_public_items)]
434    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
435        // Just print the raw handle or socket.
436        f.debug_struct("RawReadable")
437            .field("raw_handle_or_socket", &self.0)
438            .finish()
439    }
440}
441
442#[cfg(not(windows))]
443impl fmt::Debug for RawWriteable {
444    #[allow(clippy::missing_inline_in_public_items)]
445    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
446        // Just print the raw fd number.
447        f.debug_struct("RawWriteable")
448            .field("raw_fd", &self.0)
449            .finish()
450    }
451}
452
453#[cfg(windows)]
454impl fmt::Debug for RawWriteable {
455    #[allow(clippy::missing_inline_in_public_items)]
456    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
457        // Just print the raw handle or socket.
458        f.debug_struct("RawWriteable")
459            .field("raw_handle_or_socket", &self.0)
460            .finish()
461    }
462}