| 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() |
| } |
| } |