io_extras/
owned.rs

1//! `OwnedReadable` and `OwnedWriteable`.
2
3use crate::grip::{AsRawGrip, FromRawGrip, OwnedGrip};
4use crate::raw::{RawReadable, RawWriteable};
5#[cfg(not(windows))]
6use io_lifetimes::{AsFd, BorrowedFd, OwnedFd};
7use std::fmt;
8use std::io::{self, IoSlice, IoSliceMut, Read, Write};
9#[cfg(all(doc, not(windows)))]
10use std::net::TcpStream;
11#[cfg(unix)]
12use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd};
13#[cfg(target_os = "wasi")]
14use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd};
15#[cfg(windows)]
16use {
17    crate::os::windows::{
18        AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket, FromRawHandleOrSocket,
19        IntoRawHandleOrSocket, OwnedHandleOrSocket,
20    },
21    io_lifetimes::OwnedHandle,
22    std::os::windows::io::{FromRawHandle, IntoRawHandle},
23};
24
25/// An owning I/O handle that implements [`Read`].
26///
27/// This doesn't implement `Into*` or `From*` traits.
28///
29/// # Platform-specific behavior
30///
31/// On Posix-ish platforms, this reads from the handle as if it were a
32/// [`File`]. On Windows, this reads from a file-like handle as if it were a
33/// [`File`], and from a socket-like handle as if it were a [`TcpStream`].
34#[repr(transparent)]
35pub struct OwnedReadable(RawReadable);
36
37/// An owning I/O handle that implements [`Write`].
38///
39/// This doesn't implement `Into*` or `From*` traits.
40///
41/// # Platform-specific behavior
42///
43/// On Posix-ish platforms, this writes to the handle as if it were a
44/// [`File`]. On Windows, this writes to a file-like handle as if it were a
45/// [`File`], and to a socket-like handle as if it were a [`TcpStream`].
46#[repr(transparent)]
47pub struct OwnedWriteable(RawWriteable);
48
49/// `OwnedReadable` owns its handle.
50#[cfg(not(windows))]
51impl AsFd for OwnedReadable {
52    #[inline]
53    fn as_fd(&self) -> BorrowedFd<'_> {
54        unsafe { BorrowedFd::borrow_raw(self.0.as_raw_fd()) }
55    }
56}
57
58/// `OwnedReadable` owns its handle.
59#[cfg(not(windows))]
60impl From<OwnedReadable> for OwnedFd {
61    #[inline]
62    fn from(owned: OwnedReadable) -> Self {
63        unsafe { Self::from_raw_fd(owned.0.into_raw_fd()) }
64    }
65}
66
67/// `OwnedReadable` owns its handle.
68#[cfg(not(windows))]
69impl From<OwnedFd> for OwnedReadable {
70    #[inline]
71    fn from(fd: OwnedFd) -> Self {
72        unsafe { Self(RawReadable::from_raw_fd(fd.into_raw_fd())) }
73    }
74}
75
76/// `OwnedWriteable` owns its handle.
77#[cfg(not(windows))]
78impl AsFd for OwnedWriteable {
79    #[inline]
80    fn as_fd(&self) -> BorrowedFd<'_> {
81        unsafe { BorrowedFd::borrow_raw(self.0.as_raw_fd()) }
82    }
83}
84
85/// `OwnedWriteable` owns its handle.
86#[cfg(not(windows))]
87impl From<OwnedWriteable> for OwnedFd {
88    #[inline]
89    fn from(owned: OwnedWriteable) -> Self {
90        unsafe { Self::from_raw_fd(owned.0.as_raw_fd()) }
91    }
92}
93
94/// `OwnedWriteable` owns its handle.
95#[cfg(not(windows))]
96impl From<OwnedFd> for OwnedWriteable {
97    #[inline]
98    fn from(fd: OwnedFd) -> Self {
99        unsafe { Self(RawWriteable::from_raw_fd(fd.into_raw_fd())) }
100    }
101}
102
103// Windows implementations.
104
105/// `OwnedReadable` owns its handle.
106#[cfg(windows)]
107impl AsHandleOrSocket for OwnedReadable {
108    #[inline]
109    fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
110        unsafe { BorrowedHandleOrSocket::borrow_raw(self.0.as_raw_handle_or_socket()) }
111    }
112}
113
114/// `OwnedReadable` owns its handle.
115#[cfg(windows)]
116impl From<OwnedReadable> for OwnedHandleOrSocket {
117    #[inline]
118    fn from(readable: OwnedReadable) -> Self {
119        unsafe {
120            OwnedHandleOrSocket::from_raw_handle_or_socket(readable.0.into_raw_handle_or_socket())
121        }
122    }
123}
124
125/// `OwnedReadable` owns its handle.
126#[cfg(windows)]
127impl From<OwnedHandleOrSocket> for OwnedReadable {
128    #[inline]
129    fn from(handle_or_socket: OwnedHandleOrSocket) -> Self {
130        unsafe {
131            Self(RawReadable::from_raw_handle_or_socket(
132                handle_or_socket.into_raw_handle_or_socket(),
133            ))
134        }
135    }
136}
137
138/// `OwnedReadable` owns its handle.
139#[cfg(windows)]
140impl From<OwnedHandle> for OwnedReadable {
141    #[inline]
142    fn from(handle: OwnedHandle) -> Self {
143        unsafe { Self(RawReadable::from_raw_handle(handle.into_raw_handle())) }
144    }
145}
146
147/// `OwnedWriteable` owns its handle.
148#[cfg(windows)]
149impl AsHandleOrSocket for OwnedWriteable {
150    #[inline]
151    fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'_> {
152        unsafe { BorrowedHandleOrSocket::borrow_raw(self.0.as_raw_handle_or_socket()) }
153    }
154}
155
156/// `OwnedWriteable` owns its handle.
157#[cfg(windows)]
158impl From<OwnedWriteable> for OwnedHandleOrSocket {
159    #[inline]
160    fn from(writeable: OwnedWriteable) -> Self {
161        unsafe {
162            OwnedHandleOrSocket::from_raw_handle_or_socket(writeable.0.into_raw_handle_or_socket())
163        }
164    }
165}
166
167/// `OwnedWriteable` owns its handle.
168#[cfg(windows)]
169impl From<OwnedHandleOrSocket> for OwnedWriteable {
170    #[inline]
171    fn from(handle_or_socket: OwnedHandleOrSocket) -> Self {
172        unsafe {
173            Self(RawWriteable::from_raw_handle_or_socket(
174                handle_or_socket.into_raw_handle_or_socket(),
175            ))
176        }
177    }
178}
179
180/// `OwnedWriteable` owns its handle.
181#[cfg(windows)]
182impl From<OwnedHandle> for OwnedWriteable {
183    #[inline]
184    fn from(handle: OwnedHandle) -> Self {
185        unsafe { Self(RawWriteable::from_raw_handle(handle.into_raw_handle())) }
186    }
187}
188
189#[cfg(not(windows))]
190impl Read for OwnedReadable {
191    #[inline]
192    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
193        self.0.read(buf)
194    }
195
196    #[inline]
197    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
198        self.0.read_vectored(bufs)
199    }
200
201    #[cfg(can_vector)]
202    #[inline]
203    fn is_read_vectored(&self) -> bool {
204        self.0.is_read_vectored()
205    }
206
207    #[inline]
208    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
209        self.0.read_to_end(buf)
210    }
211
212    #[inline]
213    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
214        self.0.read_to_string(buf)
215    }
216
217    #[inline]
218    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
219        self.0.read_exact(buf)
220    }
221}
222
223#[cfg(windows)]
224impl Read for OwnedReadable {
225    #[inline]
226    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
227        self.0.read(buf)
228    }
229
230    #[inline]
231    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
232        self.0.read_vectored(bufs)
233    }
234
235    #[cfg(can_vector)]
236    #[inline]
237    fn is_read_vectored(&self) -> bool {
238        self.0.is_read_vectored()
239    }
240
241    #[inline]
242    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
243        self.0.read_to_end(buf)
244    }
245
246    #[inline]
247    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
248        self.0.read_to_string(buf)
249    }
250
251    #[inline]
252    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
253        self.0.read_exact(buf)
254    }
255}
256
257#[cfg(not(windows))]
258impl Write for OwnedWriteable {
259    #[inline]
260    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
261        self.0.write(buf)
262    }
263
264    #[inline]
265    fn flush(&mut self) -> io::Result<()> {
266        self.0.flush()
267    }
268
269    #[inline]
270    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
271        self.0.write_vectored(bufs)
272    }
273
274    #[cfg(can_vector)]
275    #[inline]
276    fn is_write_vectored(&self) -> bool {
277        self.0.is_write_vectored()
278    }
279
280    #[inline]
281    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
282        self.0.write_all(buf)
283    }
284
285    #[cfg(write_all_vectored)]
286    #[inline]
287    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
288        self.0.write_all_vectored(bufs)
289    }
290
291    #[inline]
292    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
293        self.0.write_fmt(fmt)
294    }
295}
296
297#[cfg(windows)]
298impl Write for OwnedWriteable {
299    #[inline]
300    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
301        self.0.write(buf)
302    }
303
304    #[inline]
305    fn flush(&mut self) -> io::Result<()> {
306        self.0.flush()
307    }
308
309    #[inline]
310    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
311        self.0.write_vectored(bufs)
312    }
313
314    #[cfg(can_vector)]
315    #[inline]
316    fn is_write_vectored(&self) -> bool {
317        self.0.is_write_vectored()
318    }
319
320    #[inline]
321    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
322        self.0.write_all(buf)
323    }
324
325    #[cfg(write_all_vectored)]
326    #[inline]
327    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
328        self.0.write_all_vectored(bufs)
329    }
330
331    #[inline]
332    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
333        self.0.write_fmt(fmt)
334    }
335}
336
337impl Drop for OwnedReadable {
338    #[inline]
339    fn drop(&mut self) {
340        unsafe {
341            let _owned = OwnedGrip::from_raw_grip(self.0.as_raw_grip());
342        }
343    }
344}
345
346impl Drop for OwnedWriteable {
347    #[inline]
348    fn drop(&mut self) {
349        unsafe {
350            let _owned = OwnedGrip::from_raw_grip(self.0.as_raw_grip());
351        }
352    }
353}
354
355#[cfg(not(windows))]
356impl fmt::Debug for OwnedReadable {
357    #[allow(clippy::missing_inline_in_public_items)]
358    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359        // Just print the raw fd number.
360        f.debug_struct("OwnedReadable")
361            .field("fd", &self.0)
362            .finish()
363    }
364}
365
366#[cfg(windows)]
367impl fmt::Debug for OwnedReadable {
368    #[allow(clippy::missing_inline_in_public_items)]
369    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
370        // Just print the raw handle or socket.
371        f.debug_struct("OwnedReadable")
372            .field("handle_or_socket", &self.0)
373            .finish()
374    }
375}
376
377#[cfg(not(windows))]
378impl fmt::Debug for OwnedWriteable {
379    #[allow(clippy::missing_inline_in_public_items)]
380    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
381        // Just print the raw fd number.
382        f.debug_struct("OwnedWriteable")
383            .field("fd", &self.0)
384            .finish()
385    }
386}
387
388#[cfg(windows)]
389impl fmt::Debug for OwnedWriteable {
390    #[allow(clippy::missing_inline_in_public_items)]
391    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
392        // Just print the raw handle or socket.
393        f.debug_struct("OwnedWriteable")
394            .field("handle_or_socket", &self.0)
395            .finish()
396    }
397}