1*bb4ee6a4SAndroid Build Coastguard Worker // Copyright 2023 The ChromiumOS Authors 2*bb4ee6a4SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*bb4ee6a4SAndroid Build Coastguard Worker // found in the LICENSE file. 4*bb4ee6a4SAndroid Build Coastguard Worker 5*bb4ee6a4SAndroid Build Coastguard Worker //! Cross platform [`IoBuf`] and [`IoBufMut`] types wrapping `iovec`/`WSABUF`. 6*bb4ee6a4SAndroid Build Coastguard Worker 7*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt; 8*bb4ee6a4SAndroid Build Coastguard Worker use std::fmt::Debug; 9*bb4ee6a4SAndroid Build Coastguard Worker use std::marker::PhantomData; 10*bb4ee6a4SAndroid Build Coastguard Worker use std::slice; 11*bb4ee6a4SAndroid Build Coastguard Worker 12*bb4ee6a4SAndroid Build Coastguard Worker pub use crate::IoBuf; 13*bb4ee6a4SAndroid Build Coastguard Worker 14*bb4ee6a4SAndroid Build Coastguard Worker pub(crate) trait PlatformIoBuf { new(ptr: *mut u8, len: usize) -> Self15*bb4ee6a4SAndroid Build Coastguard Worker fn new(ptr: *mut u8, len: usize) -> Self; len(&self) -> usize16*bb4ee6a4SAndroid Build Coastguard Worker fn len(&self) -> usize; ptr(&self) -> *mut u817*bb4ee6a4SAndroid Build Coastguard Worker fn ptr(&self) -> *mut u8; set_len(&mut self, len: usize)18*bb4ee6a4SAndroid Build Coastguard Worker fn set_len(&mut self, len: usize); set_ptr(&mut self, ptr: *mut u8)19*bb4ee6a4SAndroid Build Coastguard Worker fn set_ptr(&mut self, ptr: *mut u8); 20*bb4ee6a4SAndroid Build Coastguard Worker } 21*bb4ee6a4SAndroid Build Coastguard Worker 22*bb4ee6a4SAndroid Build Coastguard Worker /// Cross-platform mutable buffer. 23*bb4ee6a4SAndroid Build Coastguard Worker /// 24*bb4ee6a4SAndroid Build Coastguard Worker /// This type is essentialy `std::io::IoSliceMut`, and guaranteed to be ABI-compatible with 25*bb4ee6a4SAndroid Build Coastguard Worker /// `libc::iovec` on Linux/`WSABUF` on Windows; however, it does NOT automatically deref to `&mut 26*bb4ee6a4SAndroid Build Coastguard Worker /// [u8]`, which is critical because it can point to guest memory. (Guest memory is implicitly 27*bb4ee6a4SAndroid Build Coastguard Worker /// mutably borrowed by the guest, so another mutable borrow would violate Rust assumptions about 28*bb4ee6a4SAndroid Build Coastguard Worker /// references.) 29*bb4ee6a4SAndroid Build Coastguard Worker #[derive(Copy, Clone)] 30*bb4ee6a4SAndroid Build Coastguard Worker #[repr(transparent)] 31*bb4ee6a4SAndroid Build Coastguard Worker pub struct IoBufMut<'a> { 32*bb4ee6a4SAndroid Build Coastguard Worker iobuf: IoBuf, 33*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData<&'a mut [u8]>, 34*bb4ee6a4SAndroid Build Coastguard Worker } 35*bb4ee6a4SAndroid Build Coastguard Worker 36*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> IoBufMut<'a> { new(buf: &mut [u8]) -> IoBufMut<'a>37*bb4ee6a4SAndroid Build Coastguard Worker pub fn new(buf: &mut [u8]) -> IoBufMut<'a> { 38*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 39*bb4ee6a4SAndroid Build Coastguard Worker // Safe because buf's memory is of the supplied length, and 40*bb4ee6a4SAndroid Build Coastguard Worker // guaranteed to exist for the lifetime of the returned value. 41*bb4ee6a4SAndroid Build Coastguard Worker unsafe { Self::from_raw_parts(buf.as_mut_ptr(), buf.len()) } 42*bb4ee6a4SAndroid Build Coastguard Worker } 43*bb4ee6a4SAndroid Build Coastguard Worker 44*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a `IoBufMut` from a pointer and a length. 45*bb4ee6a4SAndroid Build Coastguard Worker /// 46*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety 47*bb4ee6a4SAndroid Build Coastguard Worker /// 48*bb4ee6a4SAndroid Build Coastguard Worker /// In order to use this method safely, `addr` must be valid for reads and writes of `len` bytes 49*bb4ee6a4SAndroid Build Coastguard Worker /// and should live for the entire duration of lifetime `'a`. from_raw_parts(addr: *mut u8, len: usize) -> IoBufMut<'a>50*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe fn from_raw_parts(addr: *mut u8, len: usize) -> IoBufMut<'a> { 51*bb4ee6a4SAndroid Build Coastguard Worker IoBufMut { 52*bb4ee6a4SAndroid Build Coastguard Worker iobuf: IoBuf::new(addr, len), 53*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData, 54*bb4ee6a4SAndroid Build Coastguard Worker } 55*bb4ee6a4SAndroid Build Coastguard Worker } 56*bb4ee6a4SAndroid Build Coastguard Worker 57*bb4ee6a4SAndroid Build Coastguard Worker /// Creates a `IoBufMut` from an IoBuf. 58*bb4ee6a4SAndroid Build Coastguard Worker /// 59*bb4ee6a4SAndroid Build Coastguard Worker /// # Safety 60*bb4ee6a4SAndroid Build Coastguard Worker /// 61*bb4ee6a4SAndroid Build Coastguard Worker /// In order to use this method safely, `iobuf` must be valid for reads and writes through its 62*bb4ee6a4SAndroid Build Coastguard Worker /// length and should live for the entire duration of lifetime `'a`. from_iobuf(iobuf: IoBuf) -> IoBufMut<'a>63*bb4ee6a4SAndroid Build Coastguard Worker pub unsafe fn from_iobuf(iobuf: IoBuf) -> IoBufMut<'a> { 64*bb4ee6a4SAndroid Build Coastguard Worker IoBufMut { 65*bb4ee6a4SAndroid Build Coastguard Worker iobuf, 66*bb4ee6a4SAndroid Build Coastguard Worker phantom: PhantomData, 67*bb4ee6a4SAndroid Build Coastguard Worker } 68*bb4ee6a4SAndroid Build Coastguard Worker } 69*bb4ee6a4SAndroid Build Coastguard Worker 70*bb4ee6a4SAndroid Build Coastguard Worker /// Advance the internal position of the buffer. 71*bb4ee6a4SAndroid Build Coastguard Worker /// 72*bb4ee6a4SAndroid Build Coastguard Worker /// Panics if `count > self.len()`. advance(&mut self, count: usize)73*bb4ee6a4SAndroid Build Coastguard Worker pub fn advance(&mut self, count: usize) { 74*bb4ee6a4SAndroid Build Coastguard Worker assert!(count <= self.len()); 75*bb4ee6a4SAndroid Build Coastguard Worker 76*bb4ee6a4SAndroid Build Coastguard Worker self.iobuf.set_len(self.len() - count); 77*bb4ee6a4SAndroid Build Coastguard Worker 78*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 79*bb4ee6a4SAndroid Build Coastguard Worker // Safe because we've checked that `count <= self.len()` so both the starting and resulting 80*bb4ee6a4SAndroid Build Coastguard Worker // pointer are within the bounds of the allocation. 81*bb4ee6a4SAndroid Build Coastguard Worker self.iobuf.set_ptr(unsafe { self.as_mut_ptr().add(count) }); 82*bb4ee6a4SAndroid Build Coastguard Worker } 83*bb4ee6a4SAndroid Build Coastguard Worker 84*bb4ee6a4SAndroid Build Coastguard Worker /// Shorten the length of the buffer. 85*bb4ee6a4SAndroid Build Coastguard Worker /// 86*bb4ee6a4SAndroid Build Coastguard Worker /// Has no effect if `len > self.len()`. truncate(&mut self, len: usize)87*bb4ee6a4SAndroid Build Coastguard Worker pub fn truncate(&mut self, len: usize) { 88*bb4ee6a4SAndroid Build Coastguard Worker if len < self.len() { 89*bb4ee6a4SAndroid Build Coastguard Worker self.iobuf.set_len(len); 90*bb4ee6a4SAndroid Build Coastguard Worker } 91*bb4ee6a4SAndroid Build Coastguard Worker } 92*bb4ee6a4SAndroid Build Coastguard Worker 93*bb4ee6a4SAndroid Build Coastguard Worker #[inline] len(&self) -> usize94*bb4ee6a4SAndroid Build Coastguard Worker pub fn len(&self) -> usize { 95*bb4ee6a4SAndroid Build Coastguard Worker self.iobuf.len() 96*bb4ee6a4SAndroid Build Coastguard Worker } 97*bb4ee6a4SAndroid Build Coastguard Worker 98*bb4ee6a4SAndroid Build Coastguard Worker #[inline] is_empty(&self) -> bool99*bb4ee6a4SAndroid Build Coastguard Worker pub fn is_empty(&self) -> bool { 100*bb4ee6a4SAndroid Build Coastguard Worker self.len() == 0 101*bb4ee6a4SAndroid Build Coastguard Worker } 102*bb4ee6a4SAndroid Build Coastguard Worker 103*bb4ee6a4SAndroid Build Coastguard Worker /// Gets a const pointer to this slice's memory. 104*bb4ee6a4SAndroid Build Coastguard Worker #[inline] as_ptr(&self) -> *const u8105*bb4ee6a4SAndroid Build Coastguard Worker pub fn as_ptr(&self) -> *const u8 { 106*bb4ee6a4SAndroid Build Coastguard Worker self.iobuf.ptr() as *const u8 107*bb4ee6a4SAndroid Build Coastguard Worker } 108*bb4ee6a4SAndroid Build Coastguard Worker 109*bb4ee6a4SAndroid Build Coastguard Worker /// Gets a mutable pointer to this slice's memory. 110*bb4ee6a4SAndroid Build Coastguard Worker #[inline] as_mut_ptr(&self) -> *mut u8111*bb4ee6a4SAndroid Build Coastguard Worker pub fn as_mut_ptr(&self) -> *mut u8 { 112*bb4ee6a4SAndroid Build Coastguard Worker self.iobuf.ptr() 113*bb4ee6a4SAndroid Build Coastguard Worker } 114*bb4ee6a4SAndroid Build Coastguard Worker 115*bb4ee6a4SAndroid Build Coastguard Worker /// Converts a slice of `IoBufMut`s into a slice of `IoBuf`s. 116*bb4ee6a4SAndroid Build Coastguard Worker #[allow(clippy::wrong_self_convention)] 117*bb4ee6a4SAndroid Build Coastguard Worker #[inline] as_iobufs<'slice>(iovs: &'slice [IoBufMut<'_>]) -> &'slice [IoBuf]118*bb4ee6a4SAndroid Build Coastguard Worker pub fn as_iobufs<'slice>(iovs: &'slice [IoBufMut<'_>]) -> &'slice [IoBuf] { 119*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 120*bb4ee6a4SAndroid Build Coastguard Worker // Safe because `IoBufMut` is ABI-compatible with `IoBuf`. 121*bb4ee6a4SAndroid Build Coastguard Worker unsafe { slice::from_raw_parts(iovs.as_ptr() as *const IoBuf, iovs.len()) } 122*bb4ee6a4SAndroid Build Coastguard Worker } 123*bb4ee6a4SAndroid Build Coastguard Worker 124*bb4ee6a4SAndroid Build Coastguard Worker /// Converts a mutable slice of `IoBufMut`s into a mutable slice of `IoBuf`s. 125*bb4ee6a4SAndroid Build Coastguard Worker #[inline] as_iobufs_mut<'slice>(iovs: &'slice mut [IoBufMut<'_>]) -> &'slice mut [IoBuf]126*bb4ee6a4SAndroid Build Coastguard Worker pub fn as_iobufs_mut<'slice>(iovs: &'slice mut [IoBufMut<'_>]) -> &'slice mut [IoBuf] { 127*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 128*bb4ee6a4SAndroid Build Coastguard Worker // Safe because `IoBufMut` is ABI-compatible with `IoBuf`. 129*bb4ee6a4SAndroid Build Coastguard Worker unsafe { slice::from_raw_parts_mut(iovs.as_mut_ptr() as *mut IoBuf, iovs.len()) } 130*bb4ee6a4SAndroid Build Coastguard Worker } 131*bb4ee6a4SAndroid Build Coastguard Worker } 132*bb4ee6a4SAndroid Build Coastguard Worker 133*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> AsRef<IoBuf> for IoBufMut<'a> { as_ref(&self) -> &IoBuf134*bb4ee6a4SAndroid Build Coastguard Worker fn as_ref(&self) -> &IoBuf { 135*bb4ee6a4SAndroid Build Coastguard Worker &self.iobuf 136*bb4ee6a4SAndroid Build Coastguard Worker } 137*bb4ee6a4SAndroid Build Coastguard Worker } 138*bb4ee6a4SAndroid Build Coastguard Worker 139*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> AsMut<IoBuf> for IoBufMut<'a> { as_mut(&mut self) -> &mut IoBuf140*bb4ee6a4SAndroid Build Coastguard Worker fn as_mut(&mut self) -> &mut IoBuf { 141*bb4ee6a4SAndroid Build Coastguard Worker &mut self.iobuf 142*bb4ee6a4SAndroid Build Coastguard Worker } 143*bb4ee6a4SAndroid Build Coastguard Worker } 144*bb4ee6a4SAndroid Build Coastguard Worker 145*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: 146*bb4ee6a4SAndroid Build Coastguard Worker // It's safe to implement Send + Sync for this type for the same reason that `std::io::IoSliceMut` 147*bb4ee6a4SAndroid Build Coastguard Worker // is Send + Sync. Internally, it contains a pointer and a length. The integer length is safely Send 148*bb4ee6a4SAndroid Build Coastguard Worker // + Sync. There's nothing wrong with sending a pointer between threads and de-referencing the 149*bb4ee6a4SAndroid Build Coastguard Worker // pointer requires an unsafe block anyway. See also https://github.com/rust-lang/rust/pull/70342. 150*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl<'a> Send for IoBufMut<'a> {} 151*bb4ee6a4SAndroid Build Coastguard Worker // SAFETY: See comments for impl Send 152*bb4ee6a4SAndroid Build Coastguard Worker unsafe impl<'a> Sync for IoBufMut<'a> {} 153*bb4ee6a4SAndroid Build Coastguard Worker 154*bb4ee6a4SAndroid Build Coastguard Worker impl<'a> Debug for IoBufMut<'a> { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result155*bb4ee6a4SAndroid Build Coastguard Worker fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 156*bb4ee6a4SAndroid Build Coastguard Worker f.debug_struct("IoBufMut") 157*bb4ee6a4SAndroid Build Coastguard Worker .field("ptr", &self.iobuf.ptr()) 158*bb4ee6a4SAndroid Build Coastguard Worker .field("len", &self.iobuf.len()) 159*bb4ee6a4SAndroid Build Coastguard Worker .finish() 160*bb4ee6a4SAndroid Build Coastguard Worker } 161*bb4ee6a4SAndroid Build Coastguard Worker } 162