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