Skip to content

Commit 5f6ae4a

Browse files
committed
Move IoSlice and IoSliceMut to core::io
1 parent ca9a134 commit 5f6ae4a

14 files changed

Lines changed: 629 additions & 563 deletions

File tree

library/core/src/io/io_slice.rs

Lines changed: 339 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,339 @@
1+
use crate::fmt;
2+
use crate::mem::take;
3+
use crate::ops::{Deref, DerefMut};
4+
5+
cfg_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)]
31+
pub struct IoSliceMut<'a>(repr::IoSliceMut<'a>);
32+
33+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
34+
unsafe impl<'a> Send for IoSliceMut<'a> {}
35+
36+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
37+
unsafe impl<'a> Sync for IoSliceMut<'a> {}
38+
39+
#[stable(feature = "iovec", since = "1.36.0")]
40+
impl<'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+
46+
impl<'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")]
164+
impl<'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")]
174+
impl<'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)]
189+
pub struct IoSlice<'a>(repr::IoSlice<'a>);
190+
191+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
192+
unsafe impl<'a> Send for IoSlice<'a> {}
193+
194+
#[stable(feature = "iovec_send_sync", since = "1.44.0")]
195+
unsafe impl<'a> Sync for IoSlice<'a> {}
196+
197+
#[stable(feature = "iovec", since = "1.36.0")]
198+
impl<'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+
204+
impl<'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")]
332+
impl<'a> Deref for IoSlice<'a> {
333+
type Target = [u8];
334+
335+
#[inline]
336+
fn deref(&self) -> &[u8] {
337+
self.0.as_slice()
338+
}
339+
}

0 commit comments

Comments
 (0)