1 use core::fmt; 2 use core::mem::MaybeUninit; 3 use core::ops::{ 4 Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, 5 }; 6 7 /// Uninitialized byte slice. 8 /// 9 /// Returned by `BufMut::chunk_mut()`, the referenced byte slice may be 10 /// uninitialized. The wrapper provides safe access without introducing 11 /// undefined behavior. 12 /// 13 /// The safety invariants of this wrapper are: 14 /// 15 /// 1. Reading from an `UninitSlice` is undefined behavior. 16 /// 2. Writing uninitialized bytes to an `UninitSlice` is undefined behavior. 17 /// 18 /// The difference between `&mut UninitSlice` and `&mut [MaybeUninit<u8>]` is 19 /// that it is possible in safe code to write uninitialized bytes to an 20 /// `&mut [MaybeUninit<u8>]`, which this type prohibits. 21 #[repr(transparent)] 22 pub struct UninitSlice([MaybeUninit<u8>]); 23 24 impl UninitSlice { from_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice25 pub(crate) fn from_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice { 26 unsafe { &mut *(slice as *mut [MaybeUninit<u8>] as *mut UninitSlice) } 27 } 28 29 /// Create a `&mut UninitSlice` from a pointer and a length. 30 /// 31 /// # Safety 32 /// 33 /// The caller must ensure that `ptr` references a valid memory region owned 34 /// by the caller representing a byte slice for the duration of `'a`. 35 /// 36 /// # Examples 37 /// 38 /// ``` 39 /// use bytes::buf::UninitSlice; 40 /// 41 /// let bytes = b"hello world".to_vec(); 42 /// let ptr = bytes.as_ptr() as *mut _; 43 /// let len = bytes.len(); 44 /// 45 /// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) }; 46 /// ``` 47 #[inline] from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice48 pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice { 49 let maybe_init: &mut [MaybeUninit<u8>] = 50 core::slice::from_raw_parts_mut(ptr as *mut _, len); 51 Self::from_slice(maybe_init) 52 } 53 54 /// Write a single byte at the specified offset. 55 /// 56 /// # Panics 57 /// 58 /// The function panics if `index` is out of bounds. 59 /// 60 /// # Examples 61 /// 62 /// ``` 63 /// use bytes::buf::UninitSlice; 64 /// 65 /// let mut data = [b'f', b'o', b'o']; 66 /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 67 /// 68 /// slice.write_byte(0, b'b'); 69 /// 70 /// assert_eq!(b"boo", &data[..]); 71 /// ``` 72 #[inline] write_byte(&mut self, index: usize, byte: u8)73 pub fn write_byte(&mut self, index: usize, byte: u8) { 74 assert!(index < self.len()); 75 76 unsafe { self[index..].as_mut_ptr().write(byte) } 77 } 78 79 /// Copies bytes from `src` into `self`. 80 /// 81 /// The length of `src` must be the same as `self`. 82 /// 83 /// # Panics 84 /// 85 /// The function panics if `src` has a different length than `self`. 86 /// 87 /// # Examples 88 /// 89 /// ``` 90 /// use bytes::buf::UninitSlice; 91 /// 92 /// let mut data = [b'f', b'o', b'o']; 93 /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 94 /// 95 /// slice.copy_from_slice(b"bar"); 96 /// 97 /// assert_eq!(b"bar", &data[..]); 98 /// ``` 99 #[inline] copy_from_slice(&mut self, src: &[u8])100 pub fn copy_from_slice(&mut self, src: &[u8]) { 101 use core::ptr; 102 103 assert_eq!(self.len(), src.len()); 104 105 unsafe { 106 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len()); 107 } 108 } 109 110 /// Return a raw pointer to the slice's buffer. 111 /// 112 /// # Safety 113 /// 114 /// The caller **must not** read from the referenced memory and **must not** 115 /// write **uninitialized** bytes to the slice either. 116 /// 117 /// # Examples 118 /// 119 /// ``` 120 /// use bytes::BufMut; 121 /// 122 /// let mut data = [0, 1, 2]; 123 /// let mut slice = &mut data[..]; 124 /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr(); 125 /// ``` 126 #[inline] as_mut_ptr(&mut self) -> *mut u8127 pub fn as_mut_ptr(&mut self) -> *mut u8 { 128 self.0.as_mut_ptr() as *mut _ 129 } 130 131 /// Return a `&mut [MaybeUninit<u8>]` to this slice's buffer. 132 /// 133 /// # Safety 134 /// 135 /// The caller **must not** read from the referenced memory and **must not** write 136 /// **uninitialized** bytes to the slice either. This is because `BufMut` implementation 137 /// that created the `UninitSlice` knows which parts are initialized. Writing uninitalized 138 /// bytes to the slice may cause the `BufMut` to read those bytes and trigger undefined 139 /// behavior. 140 /// 141 /// # Examples 142 /// 143 /// ``` 144 /// use bytes::BufMut; 145 /// 146 /// let mut data = [0, 1, 2]; 147 /// let mut slice = &mut data[..]; 148 /// unsafe { 149 /// let uninit_slice = BufMut::chunk_mut(&mut slice).as_uninit_slice_mut(); 150 /// }; 151 /// ``` 152 #[inline] as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>]153 pub unsafe fn as_uninit_slice_mut<'a>(&'a mut self) -> &'a mut [MaybeUninit<u8>] { 154 &mut *(self as *mut _ as *mut [MaybeUninit<u8>]) 155 } 156 157 /// Returns the number of bytes in the slice. 158 /// 159 /// # Examples 160 /// 161 /// ``` 162 /// use bytes::BufMut; 163 /// 164 /// let mut data = [0, 1, 2]; 165 /// let mut slice = &mut data[..]; 166 /// let len = BufMut::chunk_mut(&mut slice).len(); 167 /// 168 /// assert_eq!(len, 3); 169 /// ``` 170 #[inline] len(&self) -> usize171 pub fn len(&self) -> usize { 172 self.0.len() 173 } 174 } 175 176 impl fmt::Debug for UninitSlice { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result177 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 178 fmt.debug_struct("UninitSlice[...]").finish() 179 } 180 } 181 182 macro_rules! impl_index { 183 ($($t:ty),*) => { 184 $( 185 impl Index<$t> for UninitSlice { 186 type Output = UninitSlice; 187 188 #[inline] 189 fn index(&self, index: $t) -> &UninitSlice { 190 let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index]; 191 unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) } 192 } 193 } 194 195 impl IndexMut<$t> for UninitSlice { 196 #[inline] 197 fn index_mut(&mut self, index: $t) -> &mut UninitSlice { 198 let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index]; 199 unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) } 200 } 201 } 202 )* 203 }; 204 } 205 206 impl_index!( 207 Range<usize>, 208 RangeFrom<usize>, 209 RangeFull, 210 RangeInclusive<usize>, 211 RangeTo<usize>, 212 RangeToInclusive<usize> 213 ); 214