io_extras/
borrowed.rs

1//! `BorrowedReadable` and `BorrowedWriteable`.
2
3use crate::grip::{AsRawGrip, BorrowedGrip, FromRawGrip};
4#[cfg(windows)]
5use crate::os::windows::{AsHandleOrSocket, AsRawHandleOrSocket, BorrowedHandleOrSocket};
6use crate::raw::{RawReadable, RawWriteable};
7#[cfg(not(windows))]
8use io_lifetimes::{AsFd, BorrowedFd};
9use std::fmt;
10use std::io::{self, IoSlice, IoSliceMut, Read, Write};
11use std::marker::PhantomData;
12#[cfg(all(doc, not(windows)))]
13use std::net::TcpStream;
14#[cfg(unix)]
15use std::os::unix::io::AsRawFd;
16#[cfg(target_os = "wasi")]
17use std::os::wasi::io::AsRawFd;
18
19/// An owning I/O handle that implements [`Read`].
20///
21/// This doesn't implement `Into*` or `From*` traits.
22///
23/// # Platform-specific behavior
24///
25/// On Posix-ish platforms, this reads from the handle as if it were a
26/// [`File`]. On Windows, this reads from a file-like handle as if it were a
27/// [`File`], and from a socket-like handle as if it were a [`TcpStream`].
28#[repr(transparent)]
29pub struct BorrowedReadable<'a> {
30    raw: RawReadable,
31    _phantom: PhantomData<&'a ()>,
32}
33
34/// An owning I/O handle that implements [`Write`].
35///
36/// This doesn't implement `Into*` or `From*` traits.
37///
38/// # Platform-specific behavior
39///
40/// On Posix-ish platforms, this writes to the handle as if it were a
41/// [`File`]. On Windows, this writes to a file-like handle as if it were a
42/// [`File`], and to a socket-like handle as if it were a [`TcpStream`].
43#[repr(transparent)]
44pub struct BorrowedWriteable<'a> {
45    raw: RawWriteable,
46    _phantom: PhantomData<&'a ()>,
47}
48
49impl<'a> BorrowedReadable<'a> {
50    /// Create a `BorrowedReadable` that can read from a `BorrowedGrip`.
51    #[must_use]
52    #[inline]
53    pub fn borrow(grip: BorrowedGrip<'a>) -> Self {
54        Self {
55            raw: unsafe { RawReadable::from_raw_grip(grip.as_raw_grip()) },
56            _phantom: PhantomData,
57        }
58    }
59}
60
61impl<'a> BorrowedWriteable<'a> {
62    /// Create a `BorrowedReadable` that can write to a `BorrowedGrip`.
63    #[must_use]
64    #[inline]
65    pub fn borrow(grip: BorrowedGrip<'a>) -> Self {
66        Self {
67            raw: unsafe { RawWriteable::from_raw_grip(grip.as_raw_grip()) },
68            _phantom: PhantomData,
69        }
70    }
71}
72
73/// `BorrowedReadable` borrows its handle.
74#[cfg(not(windows))]
75impl<'a> AsFd for BorrowedReadable<'a> {
76    #[inline]
77    fn as_fd(&self) -> BorrowedFd<'a> {
78        unsafe { BorrowedFd::borrow_raw(self.raw.as_raw_fd()) }
79    }
80}
81
82/// `BorrowedWriteable` borrows its handle.
83#[cfg(not(windows))]
84impl<'a> AsFd for BorrowedWriteable<'a> {
85    #[inline]
86    fn as_fd(&self) -> BorrowedFd<'a> {
87        unsafe { BorrowedFd::borrow_raw(self.raw.as_raw_fd()) }
88    }
89}
90
91// Windows implementations.
92
93/// `BorrowedReadable` borrows its handle.
94#[cfg(windows)]
95impl<'a> AsHandleOrSocket for BorrowedReadable<'a> {
96    #[inline]
97    fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'a> {
98        unsafe { BorrowedHandleOrSocket::borrow_raw(self.raw.as_raw_handle_or_socket()) }
99    }
100}
101
102/// `BorrowedWriteable` borrows its handle.
103#[cfg(windows)]
104impl<'a> AsHandleOrSocket for BorrowedWriteable<'a> {
105    #[inline]
106    fn as_handle_or_socket(&self) -> BorrowedHandleOrSocket<'a> {
107        unsafe { BorrowedHandleOrSocket::borrow_raw(self.raw.as_raw_handle_or_socket()) }
108    }
109}
110
111#[cfg(not(windows))]
112impl<'a> Read for BorrowedReadable<'a> {
113    #[inline]
114    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
115        self.raw.read(buf)
116    }
117
118    #[inline]
119    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
120        self.raw.read_vectored(bufs)
121    }
122
123    #[cfg(can_vector)]
124    #[inline]
125    fn is_read_vectored(&self) -> bool {
126        self.raw.is_read_vectored()
127    }
128
129    #[inline]
130    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
131        self.raw.read_to_end(buf)
132    }
133
134    #[inline]
135    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
136        self.raw.read_to_string(buf)
137    }
138
139    #[inline]
140    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
141        self.raw.read_exact(buf)
142    }
143}
144
145#[cfg(windows)]
146impl<'a> Read for BorrowedReadable<'a> {
147    #[inline]
148    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
149        self.raw.read(buf)
150    }
151
152    #[inline]
153    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
154        self.raw.read_vectored(bufs)
155    }
156
157    #[cfg(can_vector)]
158    #[inline]
159    fn is_read_vectored(&self) -> bool {
160        self.raw.is_read_vectored()
161    }
162
163    #[inline]
164    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
165        self.raw.read_to_end(buf)
166    }
167
168    #[inline]
169    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
170        self.raw.read_to_string(buf)
171    }
172
173    #[inline]
174    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
175        self.raw.read_exact(buf)
176    }
177}
178
179#[cfg(not(windows))]
180impl<'a> Write for BorrowedWriteable<'a> {
181    #[inline]
182    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
183        self.raw.write(buf)
184    }
185
186    #[inline]
187    fn flush(&mut self) -> io::Result<()> {
188        self.raw.flush()
189    }
190
191    #[inline]
192    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
193        self.raw.write_vectored(bufs)
194    }
195
196    #[cfg(can_vector)]
197    #[inline]
198    fn is_write_vectored(&self) -> bool {
199        self.raw.is_write_vectored()
200    }
201
202    #[inline]
203    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
204        self.raw.write_all(buf)
205    }
206
207    #[cfg(write_all_vectored)]
208    #[inline]
209    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
210        self.raw.write_all_vectored(bufs)
211    }
212
213    #[inline]
214    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
215        self.raw.write_fmt(fmt)
216    }
217}
218
219#[cfg(windows)]
220impl<'a> Write for BorrowedWriteable<'a> {
221    #[inline]
222    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
223        self.raw.write(buf)
224    }
225
226    #[inline]
227    fn flush(&mut self) -> io::Result<()> {
228        self.raw.flush()
229    }
230
231    #[inline]
232    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
233        self.raw.write_vectored(bufs)
234    }
235
236    #[cfg(can_vector)]
237    #[inline]
238    fn is_write_vectored(&self) -> bool {
239        self.raw.is_write_vectored()
240    }
241
242    #[inline]
243    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
244        self.raw.write_all(buf)
245    }
246
247    #[cfg(write_all_vectored)]
248    #[inline]
249    fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> {
250        self.raw.write_all_vectored(bufs)
251    }
252
253    #[inline]
254    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> {
255        self.raw.write_fmt(fmt)
256    }
257}
258
259#[cfg(not(windows))]
260impl<'a> fmt::Debug for BorrowedReadable<'a> {
261    #[allow(clippy::missing_inline_in_public_items)]
262    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263        // Just print the raw fd number.
264        f.debug_struct("BorrowedReadable")
265            .field("fd", &self.raw)
266            .finish()
267    }
268}
269
270#[cfg(windows)]
271impl<'a> fmt::Debug for BorrowedReadable<'a> {
272    #[allow(clippy::missing_inline_in_public_items)]
273    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274        // Just print the raw handle or socket.
275        f.debug_struct("BorrowedReadable")
276            .field("handle_or_socket", &self.raw)
277            .finish()
278    }
279}
280
281#[cfg(not(windows))]
282impl<'a> fmt::Debug for BorrowedWriteable<'a> {
283    #[allow(clippy::missing_inline_in_public_items)]
284    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
285        // Just print the raw fd number.
286        f.debug_struct("BorrowedWriteable")
287            .field("fd", &self.raw)
288            .finish()
289    }
290}
291
292#[cfg(windows)]
293impl<'a> fmt::Debug for BorrowedWriteable<'a> {
294    #[allow(clippy::missing_inline_in_public_items)]
295    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296        // Just print the raw handle or socket.
297        f.debug_struct("BorrowedWriteable")
298            .field("handle_or_socket", &self.raw)
299            .finish()
300    }
301}