| use crate::fmt; | |
| use crate::mem::take; | |
| use crate::ops::{Deref, DerefMut}; | |
| cfg_select! { | |
| any(target_family = "unix", target_os = "hermit", target_os = "solid_asp3", target_os = "trusty", target_os = "wasi") => { | |
| #[path = "io_slice/repr_iovec.rs"] | |
| mod repr; | |
| } | |
| target_os = "windows" => { | |
| #[path = "io_slice/repr_windows.rs"] | |
| mod repr; | |
| } | |
| target_os = "uefi" => { | |
| #[path = "io_slice/repr_uefi.rs"] | |
| mod repr; | |
| } | |
| _ => { | |
| #[path = "io_slice/repr_generic.rs"] | |
| mod repr; | |
| } | |
| } | |
| /// A buffer type used with `Read::read_vectored`. | |
| /// | |
| /// It is semantically a wrapper around a `&mut [u8]`, but is guaranteed to be | |
| /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on | |
| /// Windows. | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| #[repr(transparent)] | |
| pub struct IoSliceMut<'a>(repr::IoSliceMut<'a>); | |
| #[stable(feature = "iovec_send_sync", since = "1.44.0")] | |
| unsafe impl<'a> Send for IoSliceMut<'a> {} | |
| #[stable(feature = "iovec_send_sync", since = "1.44.0")] | |
| unsafe impl<'a> Sync for IoSliceMut<'a> {} | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| impl<'a> fmt::Debug for IoSliceMut<'a> { | |
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| fmt::Debug::fmt(self.0.as_slice(), fmt) | |
| } | |
| } | |
| impl<'a> IoSliceMut<'a> { | |
| /// Creates a new `IoSliceMut` wrapping a byte slice. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics on Windows if the slice is larger than 4GB. | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| #[inline] | |
| pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> { | |
| IoSliceMut(repr::IoSliceMut::new(buf)) | |
| } | |
| /// Advance the internal cursor of the slice. | |
| /// | |
| /// Also see [`IoSliceMut::advance_slices`] to advance the cursors of | |
| /// multiple buffers. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics when trying to advance beyond the end of the slice. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::io::IoSliceMut; | |
| /// use std::ops::Deref; | |
| /// | |
| /// let mut data = [1; 8]; | |
| /// let mut buf = IoSliceMut::new(&mut data); | |
| /// | |
| /// // Mark 3 bytes as read. | |
| /// buf.advance(3); | |
| /// assert_eq!(buf.deref(), [1; 5].as_ref()); | |
| /// ``` | |
| #[stable(feature = "io_slice_advance", since = "1.81.0")] | |
| #[inline] | |
| pub fn advance(&mut self, n: usize) { | |
| self.0.advance(n) | |
| } | |
| /// Advance a slice of slices. | |
| /// | |
| /// Shrinks the slice to remove any `IoSliceMut`s that are fully advanced over. | |
| /// If the cursor ends up in the middle of an `IoSliceMut`, it is modified | |
| /// to start at that cursor. | |
| /// | |
| /// For example, if we have a slice of two 8-byte `IoSliceMut`s, and we advance by 10 bytes, | |
| /// the result will only include the second `IoSliceMut`, advanced by 2 bytes. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics when trying to advance beyond the end of the slices. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::io::IoSliceMut; | |
| /// use std::ops::Deref; | |
| /// | |
| /// let mut buf1 = [1; 8]; | |
| /// let mut buf2 = [2; 16]; | |
| /// let mut buf3 = [3; 8]; | |
| /// let mut bufs = &mut [ | |
| /// IoSliceMut::new(&mut buf1), | |
| /// IoSliceMut::new(&mut buf2), | |
| /// IoSliceMut::new(&mut buf3), | |
| /// ][..]; | |
| /// | |
| /// // Mark 10 bytes as read. | |
| /// IoSliceMut::advance_slices(&mut bufs, 10); | |
| /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); | |
| /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); | |
| /// ``` | |
| #[stable(feature = "io_slice_advance", since = "1.81.0")] | |
| #[inline] | |
| pub fn advance_slices(bufs: &mut &mut [IoSliceMut<'a>], n: usize) { | |
| // Number of buffers to remove. | |
| let mut remove = 0; | |
| // Remaining length before reaching n. | |
| let mut left = n; | |
| for buf in bufs.iter() { | |
| if let Some(remainder) = left.checked_sub(buf.len()) { | |
| left = remainder; | |
| remove += 1; | |
| } else { | |
| break; | |
| } | |
| } | |
| *bufs = &mut take(bufs)[remove..]; | |
| if bufs.is_empty() { | |
| assert!(left == 0, "advancing io slices beyond their length"); | |
| } else { | |
| bufs[0].advance(left); | |
| } | |
| } | |
| /// Get the underlying bytes as a mutable slice with the original lifetime. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(io_slice_as_bytes)] | |
| /// use std::io::IoSliceMut; | |
| /// | |
| /// let mut data = *b"abcdef"; | |
| /// let io_slice = IoSliceMut::new(&mut data); | |
| /// io_slice.into_slice()[0] = b'A'; | |
| /// | |
| /// assert_eq!(&data, b"Abcdef"); | |
| /// ``` | |
| #[unstable(feature = "io_slice_as_bytes", issue = "132818")] | |
| pub const fn into_slice(self) -> &'a mut [u8] { | |
| self.0.into_slice() | |
| } | |
| } | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| impl<'a> Deref for IoSliceMut<'a> { | |
| type Target = [u8]; | |
| #[inline] | |
| fn deref(&self) -> &[u8] { | |
| self.0.as_slice() | |
| } | |
| } | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| impl<'a> DerefMut for IoSliceMut<'a> { | |
| #[inline] | |
| fn deref_mut(&mut self) -> &mut [u8] { | |
| self.0.as_mut_slice() | |
| } | |
| } | |
| /// A buffer type used with `Write::write_vectored`. | |
| /// | |
| /// It is semantically a wrapper around a `&[u8]`, but is guaranteed to be | |
| /// ABI compatible with the `iovec` type on Unix platforms and `WSABUF` on | |
| /// Windows. | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| #[derive(Copy, Clone)] | |
| #[repr(transparent)] | |
| pub struct IoSlice<'a>(repr::IoSlice<'a>); | |
| #[stable(feature = "iovec_send_sync", since = "1.44.0")] | |
| unsafe impl<'a> Send for IoSlice<'a> {} | |
| #[stable(feature = "iovec_send_sync", since = "1.44.0")] | |
| unsafe impl<'a> Sync for IoSlice<'a> {} | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| impl<'a> fmt::Debug for IoSlice<'a> { | |
| fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { | |
| fmt::Debug::fmt(self.0.as_slice(), fmt) | |
| } | |
| } | |
| impl<'a> IoSlice<'a> { | |
| /// Creates a new `IoSlice` wrapping a byte slice. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics on Windows if the slice is larger than 4GB. | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| #[must_use] | |
| #[inline] | |
| pub fn new(buf: &'a [u8]) -> IoSlice<'a> { | |
| IoSlice(repr::IoSlice::new(buf)) | |
| } | |
| /// Advance the internal cursor of the slice. | |
| /// | |
| /// Also see [`IoSlice::advance_slices`] to advance the cursors of multiple | |
| /// buffers. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics when trying to advance beyond the end of the slice. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::io::IoSlice; | |
| /// use std::ops::Deref; | |
| /// | |
| /// let data = [1; 8]; | |
| /// let mut buf = IoSlice::new(&data); | |
| /// | |
| /// // Mark 3 bytes as read. | |
| /// buf.advance(3); | |
| /// assert_eq!(buf.deref(), [1; 5].as_ref()); | |
| /// ``` | |
| #[stable(feature = "io_slice_advance", since = "1.81.0")] | |
| #[inline] | |
| pub fn advance(&mut self, n: usize) { | |
| self.0.advance(n) | |
| } | |
| /// Advance a slice of slices. | |
| /// | |
| /// Shrinks the slice to remove any `IoSlice`s that are fully advanced over. | |
| /// If the cursor ends up in the middle of an `IoSlice`, it is modified | |
| /// to start at that cursor. | |
| /// | |
| /// For example, if we have a slice of two 8-byte `IoSlice`s, and we advance by 10 bytes, | |
| /// the result will only include the second `IoSlice`, advanced by 2 bytes. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics when trying to advance beyond the end of the slices. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// use std::io::IoSlice; | |
| /// use std::ops::Deref; | |
| /// | |
| /// let buf1 = [1; 8]; | |
| /// let buf2 = [2; 16]; | |
| /// let buf3 = [3; 8]; | |
| /// let mut bufs = &mut [ | |
| /// IoSlice::new(&buf1), | |
| /// IoSlice::new(&buf2), | |
| /// IoSlice::new(&buf3), | |
| /// ][..]; | |
| /// | |
| /// // Mark 10 bytes as written. | |
| /// IoSlice::advance_slices(&mut bufs, 10); | |
| /// assert_eq!(bufs[0].deref(), [2; 14].as_ref()); | |
| /// assert_eq!(bufs[1].deref(), [3; 8].as_ref()); | |
| #[stable(feature = "io_slice_advance", since = "1.81.0")] | |
| #[inline] | |
| pub fn advance_slices(bufs: &mut &mut [IoSlice<'a>], n: usize) { | |
| // Number of buffers to remove. | |
| let mut remove = 0; | |
| // Remaining length before reaching n. This prevents overflow | |
| // that could happen if the length of slices in `bufs` were instead | |
| // accumulated. Those slice may be aliased and, if they are large | |
| // enough, their added length may overflow a `usize`. | |
| let mut left = n; | |
| for buf in bufs.iter() { | |
| if let Some(remainder) = left.checked_sub(buf.len()) { | |
| left = remainder; | |
| remove += 1; | |
| } else { | |
| break; | |
| } | |
| } | |
| *bufs = &mut take(bufs)[remove..]; | |
| if bufs.is_empty() { | |
| assert!(left == 0, "advancing io slices beyond their length"); | |
| } else { | |
| bufs[0].advance(left); | |
| } | |
| } | |
| /// Get the underlying bytes as a slice with the original lifetime. | |
| /// | |
| /// This doesn't borrow from `self`, so is less restrictive than calling | |
| /// `.deref()`, which does. | |
| /// | |
| /// # Examples | |
| /// | |
| /// ``` | |
| /// #![feature(io_slice_as_bytes)] | |
| /// use std::io::IoSlice; | |
| /// | |
| /// let data = b"abcdef"; | |
| /// | |
| /// let mut io_slice = IoSlice::new(data); | |
| /// let tail = &io_slice.as_slice()[3..]; | |
| /// | |
| /// // This works because `tail` doesn't borrow `io_slice` | |
| /// io_slice = IoSlice::new(tail); | |
| /// | |
| /// assert_eq!(io_slice.as_slice(), b"def"); | |
| /// ``` | |
| #[unstable(feature = "io_slice_as_bytes", issue = "132818")] | |
| pub const fn as_slice(self) -> &'a [u8] { | |
| self.0.as_slice() | |
| } | |
| } | |
| #[stable(feature = "iovec", since = "1.36.0")] | |
| impl<'a> Deref for IoSlice<'a> { | |
| type Target = [u8]; | |
| #[inline] | |
| fn deref(&self) -> &[u8] { | |
| self.0.as_slice() | |
| } | |
| } |