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}