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 | 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 ] |
48 | 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 ] |
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 ] |
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 ] |
127 | 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 ] |
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 ] |
171 | pub fn len(&self) -> usize { |
172 | self.0.len() |
173 | } |
174 | } |
175 | |
176 | impl fmt::Debug for UninitSlice { |
177 | fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { |
178 | fmt.debug_struct(name:"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 | |