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 { 25 /// Create a `&mut UninitSlice` from a pointer and a length. 26 /// 27 /// # Safety 28 /// 29 /// The caller must ensure that `ptr` references a valid memory region owned 30 /// by the caller representing a byte slice for the duration of `'a`. 31 /// 32 /// # Examples 33 /// 34 /// ``` 35 /// use bytes::buf::UninitSlice; 36 /// 37 /// let bytes = b"hello world".to_vec(); 38 /// let ptr = bytes.as_ptr() as *mut _; 39 /// let len = bytes.len(); 40 /// 41 /// let slice = unsafe { UninitSlice::from_raw_parts_mut(ptr, len) }; 42 /// ``` 43 #[inline] from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice44 pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice { 45 let maybe_init: &mut [MaybeUninit<u8>] = 46 core::slice::from_raw_parts_mut(ptr as *mut _, len); 47 &mut *(maybe_init as *mut [MaybeUninit<u8>] as *mut UninitSlice) 48 } 49 50 /// Write a single byte at the specified offset. 51 /// 52 /// # Panics 53 /// 54 /// The function panics if `index` is out of bounds. 55 /// 56 /// # Examples 57 /// 58 /// ``` 59 /// use bytes::buf::UninitSlice; 60 /// 61 /// let mut data = [b'f', b'o', b'o']; 62 /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 63 /// 64 /// slice.write_byte(0, b'b'); 65 /// 66 /// assert_eq!(b"boo", &data[..]); 67 /// ``` 68 #[inline] write_byte(&mut self, index: usize, byte: u8)69 pub fn write_byte(&mut self, index: usize, byte: u8) { 70 assert!(index < self.len()); 71 72 unsafe { self[index..].as_mut_ptr().write(byte) } 73 } 74 75 /// Copies bytes from `src` into `self`. 76 /// 77 /// The length of `src` must be the same as `self`. 78 /// 79 /// # Panics 80 /// 81 /// The function panics if `src` has a different length than `self`. 82 /// 83 /// # Examples 84 /// 85 /// ``` 86 /// use bytes::buf::UninitSlice; 87 /// 88 /// let mut data = [b'f', b'o', b'o']; 89 /// let slice = unsafe { UninitSlice::from_raw_parts_mut(data.as_mut_ptr(), 3) }; 90 /// 91 /// slice.copy_from_slice(b"bar"); 92 /// 93 /// assert_eq!(b"bar", &data[..]); 94 /// ``` 95 #[inline] copy_from_slice(&mut self, src: &[u8])96 pub fn copy_from_slice(&mut self, src: &[u8]) { 97 use core::ptr; 98 99 assert_eq!(self.len(), src.len()); 100 101 unsafe { 102 ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len()); 103 } 104 } 105 106 /// Return a raw pointer to the slice's buffer. 107 /// 108 /// # Safety 109 /// 110 /// The caller **must not** read from the referenced memory and **must not** 111 /// write **uninitialized** bytes to the slice either. 112 /// 113 /// # Examples 114 /// 115 /// ``` 116 /// use bytes::BufMut; 117 /// 118 /// let mut data = [0, 1, 2]; 119 /// let mut slice = &mut data[..]; 120 /// let ptr = BufMut::chunk_mut(&mut slice).as_mut_ptr(); 121 /// ``` 122 #[inline] as_mut_ptr(&mut self) -> *mut u8123 pub fn as_mut_ptr(&mut self) -> *mut u8 { 124 self.0.as_mut_ptr() as *mut _ 125 } 126 127 /// Returns the number of bytes in the slice. 128 /// 129 /// # Examples 130 /// 131 /// ``` 132 /// use bytes::BufMut; 133 /// 134 /// let mut data = [0, 1, 2]; 135 /// let mut slice = &mut data[..]; 136 /// let len = BufMut::chunk_mut(&mut slice).len(); 137 /// 138 /// assert_eq!(len, 3); 139 /// ``` 140 #[inline] len(&self) -> usize141 pub fn len(&self) -> usize { 142 self.0.len() 143 } 144 } 145 146 impl fmt::Debug for UninitSlice { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result147 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 148 fmt.debug_struct("UninitSlice[...]").finish() 149 } 150 } 151 152 macro_rules! impl_index { 153 ($($t:ty),*) => { 154 $( 155 impl Index<$t> for UninitSlice { 156 type Output = UninitSlice; 157 158 #[inline] 159 fn index(&self, index: $t) -> &UninitSlice { 160 let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index]; 161 unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) } 162 } 163 } 164 165 impl IndexMut<$t> for UninitSlice { 166 #[inline] 167 fn index_mut(&mut self, index: $t) -> &mut UninitSlice { 168 let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index]; 169 unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) } 170 } 171 } 172 )* 173 }; 174 } 175 176 impl_index!( 177 Range<usize>, 178 RangeFrom<usize>, 179 RangeFull, 180 RangeInclusive<usize>, 181 RangeTo<usize>, 182 RangeToInclusive<usize> 183 ); 184