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}