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