Skip to main content

core/io/
io_slice.rs

1use crate::fmt;
2use crate::mem::take;
3use crate::ops::{Deref, DerefMut};
4
5cfg_select! {
6    any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => {
7        #[path = "io_slice/repr_iovec.rs"]
8        mod repr;
9    }
10    target_os = "windows" => {
11        #[path = "io_slice/repr_windows.rs"]
12        mod repr;
13    }
14    target_os = "uefi" => {
15        #[path = "io_slice/repr_uefi.rs"]
16        mod repr;
17    }
18    _ => {
19        #[path = "io_slice/repr_generic.rs"]
20        mod repr;
21    }
22}
23
24/// A buffer type used with `Read::read_vectored`.
25///
26/// It is semantically a wrapper around a `&mut [u8]`, but is guaranteed to be
27/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
28/// Windows.
29#[stable(feature = "iovec", since = "1.36.0")]
30#[repr(transparent)]
31pub struct IoSliceMut<'a>(repr::IoSliceMut<'a>);
32
33#[stable(feature = "iovec_send_sync", since = "1.44.0")]
34unsafe impl<'a> Send for IoSliceMut<'a> {}
35
36#[stable(feature = "iovec_send_sync", since = "1.44.0")]
37unsafe impl<'a> Sync for IoSliceMut<'a> {}
38
39#[stable(feature = "iovec", since = "1.36.0")]
40impl<'a> fmt::Debug for IoSliceMut<'a> {
41    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
42        fmt::Debug::fmt(self.0.as_slice(), fmt)
43    }
44}
45
46impl<'a> IoSliceMut<'a> {
47    /// Creates a new `IoSliceMut` wrapping a byte slice.
48    ///
49    /// # Panics
50    ///
51    /// Panics on Windows if the slice is larger than 4GB.
52    #[stable(feature = "iovec", since = "1.36.0")]
53    #[inline]
54    pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
55        IoSliceMut(repr::IoSliceMut::new(buf))
56    }
57
58    /// Advance the internal cursor of the slice.
59    ///
60    /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of
61    /// multiple buffers.
62    ///
63    /// # Panics
64    ///
65    /// Panics when trying to advance beyond the end of the slice.
66    ///
67    /// # Examples
68    ///
69    /// ```
70    /// use std::io::IoSliceMut;
71    /// use std::ops::Deref;
72    ///
73    /// let mut data = [1; 8];
74    /// let mut buf = IoSliceMut::new(&mut data);
75    ///
76    /// // Mark 3 bytes as read.
77    /// buf.advance(3);
78    /// assert_eq!(buf.deref(), [1; 5].as_ref());
79    /// ```
80    #[stable(feature = "io_slice_advance", since = "1.81.0")]
81    #[inline]
82    pub fn advance(&mut self, n: usize) {
83        self.0.advance(n)
84    }
85
86    /// Advance a slice of slices.
87    ///
88    /// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over.
89    /// If the cursor ends up in the middle of an `IoSliceMut`, it is modified
90    /// to start at that cursor.
91    ///
92    /// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes,
93    /// the result will only include the second `IoSliceMut`, advanced by 2 bytes.
94    ///
95    /// # Panics
96    ///
97    /// Panics when trying to advance beyond the end of the slices.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use std::io::IoSliceMut;
103    /// use std::ops::Deref;
104    ///
105    /// let mut buf1 = [1; 8];
106    /// let mut buf2 = [2; 16];
107    /// let mut buf3 = [3; 8];
108    /// let mut bufs = &mut [
109    ///     IoSliceMut::new(&mut buf1),
110    ///     IoSliceMut::new(&mut buf2),
111    ///     IoSliceMut::new(&mut buf3),
112    /// ][..];
113    ///
114    /// // Mark 10 bytes as read.
115    /// IoSliceMut::advance_slices(&mut bufs, 10);
116    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
117    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
118    /// ```
119    #[stable(feature = "io_slice_advance", since = "1.81.0")]
120    #[inline]
121    pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) {
122        // Number of buffers to remove.
123        let mut remove = 0;
124        // Remaining length before reaching n.
125        let mut left = n;
126        for buf in bufs.iter() {
127            if let Some(remainder) = left.checked_sub(buf.len()) {
128                left = remainder;
129                remove += 1;
130            } else {
131                break;
132            }
133        }
134
135        *bufs = &mut take(bufs)[remove..];
136        if bufs.is_empty() {
137            assert!(left == 0, "advancing io slices beyond their length");
138        } else {
139            bufs[0].advance(left);
140        }
141    }
142
143    /// Get the underlying bytes as a mutable slice with the original lifetime.
144    ///
145    /// # Examples
146    ///
147    /// ```
148    /// #![feature(io_slice_as_bytes)]
149    /// use std::io::IoSliceMut;
150    ///
151    /// let mut data = *b"abcdef";
152    /// let io_slice = IoSliceMut::new(&mut data);
153    /// io_slice.into_slice()[0] = b'A';
154    ///
155    /// assert_eq!(&data, b"Abcdef");
156    /// ```
157    #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
158    pub const fn into_slice(self) -> &'a mut [u8] {
159        self.0.into_slice()
160    }
161}
162
163#[stable(feature = "iovec", since = "1.36.0")]
164impl<'a> Deref for IoSliceMut<'a> {
165    type Target = [u8];
166
167    #[inline]
168    fn deref(&self) -> &[u8] {
169        self.0.as_slice()
170    }
171}
172
173#[stable(feature = "iovec", since = "1.36.0")]
174impl<'a> DerefMut for IoSliceMut<'a> {
175    #[inline]
176    fn deref_mut(&mut self) -> &mut [u8] {
177        self.0.as_mut_slice()
178    }
179}
180
181/// A buffer type used with `Write::write_vectored`.
182///
183/// It is semantically a wrapper around a `&[u8]`, but is guaranteed to be
184/// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on
185/// Windows.
186#[stable(feature = "iovec", since = "1.36.0")]
187#[derive(Copy, Clone)]
188#[repr(transparent)]
189pub struct IoSlice<'a>(repr::IoSlice<'a>);
190
191#[stable(feature = "iovec_send_sync", since = "1.44.0")]
192unsafe impl<'a> Send for IoSlice<'a> {}
193
194#[stable(feature = "iovec_send_sync", since = "1.44.0")]
195unsafe impl<'a> Sync for IoSlice<'a> {}
196
197#[stable(feature = "iovec", since = "1.36.0")]
198impl<'a> fmt::Debug for IoSlice<'a> {
199    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
200        fmt::Debug::fmt(self.0.as_slice(), fmt)
201    }
202}
203
204impl<'a> IoSlice<'a> {
205    /// Creates a new `IoSlice` wrapping a byte slice.
206    ///
207    /// # Panics
208    ///
209    /// Panics on Windows if the slice is larger than 4GB.
210    #[stable(feature = "iovec", since = "1.36.0")]
211    #[must_use]
212    #[inline]
213    pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
214        IoSlice(repr::IoSlice::new(buf))
215    }
216
217    /// Advance the internal cursor of the slice.
218    ///
219    /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple
220    /// buffers.
221    ///
222    /// # Panics
223    ///
224    /// Panics when trying to advance beyond the end of the slice.
225    ///
226    /// # Examples
227    ///
228    /// ```
229    /// use std::io::IoSlice;
230    /// use std::ops::Deref;
231    ///
232    /// let data = [1; 8];
233    /// let mut buf = IoSlice::new(&data);
234    ///
235    /// // Mark 3 bytes as read.
236    /// buf.advance(3);
237    /// assert_eq!(buf.deref(), [1; 5].as_ref());
238    /// ```
239    #[stable(feature = "io_slice_advance", since = "1.81.0")]
240    #[inline]
241    pub fn advance(&mut self, n: usize) {
242        self.0.advance(n)
243    }
244
245    /// Advance a slice of slices.
246    ///
247    /// Shrinks the slice to remove any `IoSlice`s that are fully advanced over.
248    /// If the cursor ends up in the middle of an `IoSlice`, it is modified
249    /// to start at that cursor.
250    ///
251    /// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes,
252    /// the result will only include the second `IoSlice`, advanced by 2 bytes.
253    ///
254    /// # Panics
255    ///
256    /// Panics when trying to advance beyond the end of the slices.
257    ///
258    /// # Examples
259    ///
260    /// ```
261    /// use std::io::IoSlice;
262    /// use std::ops::Deref;
263    ///
264    /// let buf1 = [1; 8];
265    /// let buf2 = [2; 16];
266    /// let buf3 = [3; 8];
267    /// let mut bufs = &mut [
268    ///     IoSlice::new(&buf1),
269    ///     IoSlice::new(&buf2),
270    ///     IoSlice::new(&buf3),
271    /// ][..];
272    ///
273    /// // Mark 10 bytes as written.
274    /// IoSlice::advance_slices(&mut bufs, 10);
275    /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
276    /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
277    #[stable(feature = "io_slice_advance", since = "1.81.0")]
278    #[inline]
279    pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) {
280        // Number of buffers to remove.
281        let mut remove = 0;
282        // Remaining length before reaching n. This prevents overflow
283        // that could happen if the length of slices in `bufs` were instead
284        // accumulated. Those slice may be aliased and, if they are large
285        // enough, their added length may overflow a `usize`.
286        let mut left = n;
287        for buf in bufs.iter() {
288            if let Some(remainder) = left.checked_sub(buf.len()) {
289                left = remainder;
290                remove += 1;
291            } else {
292                break;
293            }
294        }
295
296        *bufs = &mut take(bufs)[remove..];
297        if bufs.is_empty() {
298            assert!(left == 0, "advancing io slices beyond their length");
299        } else {
300            bufs[0].advance(left);
301        }
302    }
303
304    /// Get the underlying bytes as a slice with the original lifetime.
305    ///
306    /// This doesn't borrow from `self`, so is less restrictive than calling
307    /// `.deref()`, which does.
308    ///
309    /// # Examples
310    ///
311    /// ```
312    /// #![feature(io_slice_as_bytes)]
313    /// use std::io::IoSlice;
314    ///
315    /// let data = b"abcdef";
316    ///
317    /// let mut io_slice = IoSlice::new(data);
318    /// let tail = &io_slice.as_slice()[3..];
319    ///
320    /// // This works because `tail` doesn't borrow `io_slice`
321    /// io_slice = IoSlice::new(tail);
322    ///
323    /// assert_eq!(io_slice.as_slice(), b"def");
324    /// ```
325    #[unstable(feature = "io_slice_as_bytes", issue = "132818")]
326    pub const fn as_slice(self) -> &'a [u8] {
327        self.0.as_slice()
328    }
329}
330
331#[stable(feature = "iovec", since = "1.36.0")]
332impl<'a> Deref for IoSlice<'a> {
333    type Target = [u8];
334
335    #[inline]
336    fn deref(&self) -> &[u8] {
337        self.0.as_slice()
338    }
339}