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