Skip to content

Commit 99a2754

Browse files
authored
Add a safe way to create UninitSlice from slices (#598)
Introduce UninitSlice::from_slice and UninitSlice::from_uninit_slice methods which safely create Uninit slice from provided slice of maybe uninitialised or initialised memory. In addition, add `From<&mut [T]>` implementations (for `T=u8` and `T=MaybeUninit<u8>`) which do conversion from slice to UninitSlice. Closes: #552
1 parent 74b04c7 commit 99a2754

File tree

2 files changed

+51
-7
lines changed

2 files changed

+51
-7
lines changed

src/buf/uninit_slice.rs

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,44 @@ use core::ops::{
2222
pub struct UninitSlice([MaybeUninit<u8>]);
2323

2424
impl UninitSlice {
25-
pub(crate) fn from_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice {
25+
/// Creates a `&mut UninitSlice` wrapping slice of uninitialised memory.
26+
///
27+
/// # Examples
28+
///
29+
/// ```
30+
/// use bytes::buf::UninitSlice;
31+
/// use core::mem::MaybeUninit;
32+
///
33+
/// let mut buffer = [MaybeUninit::uninit(); 64];
34+
/// let slice = UninitSlice::from_uninit_slice(&mut buffer[..]);
35+
///
36+
/// let mut vec = Vec::with_capacity(1024);
37+
/// let spare: &mut UninitSlice = vec.spare_capacity_mut().into();
38+
/// ```
39+
#[inline]
40+
pub fn from_uninit_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice {
2641
unsafe { &mut *(slice as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
2742
}
2843

44+
fn from_uninit_slice_ref(slice: &[MaybeUninit<u8>]) -> &UninitSlice {
45+
unsafe { &*(slice as *const [MaybeUninit<u8>] as *const UninitSlice) }
46+
}
47+
48+
/// Creates a `&mut UninitSlice` wrapping slice of initialised memory.
49+
///
50+
/// # Examples
51+
///
52+
/// ```
53+
/// use bytes::buf::UninitSlice;
54+
///
55+
/// let mut buffer = [0u8; 64];
56+
/// let slice = UninitSlice::from_slice(&mut buffer[..]);
57+
/// ```
58+
#[inline]
59+
pub fn from_slice(slice: &mut [u8]) -> &mut UninitSlice {
60+
unsafe { &mut *(slice as *mut [u8] as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
61+
}
62+
2963
/// Create a `&mut UninitSlice` from a pointer and a length.
3064
///
3165
/// # Safety
@@ -48,7 +82,7 @@ impl UninitSlice {
4882
pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
4983
let maybe_init: &mut [MaybeUninit<u8>] =
5084
core::slice::from_raw_parts_mut(ptr as *mut _, len);
51-
Self::from_slice(maybe_init)
85+
Self::from_uninit_slice(maybe_init)
5286
}
5387

5488
/// Write a single byte at the specified offset.
@@ -179,6 +213,18 @@ impl fmt::Debug for UninitSlice {
179213
}
180214
}
181215

216+
impl<'a> From<&'a mut [u8]> for &'a mut UninitSlice {
217+
fn from(slice: &'a mut [u8]) -> Self {
218+
UninitSlice::from_slice(slice)
219+
}
220+
}
221+
222+
impl<'a> From<&'a mut [MaybeUninit<u8>]> for &'a mut UninitSlice {
223+
fn from(slice: &'a mut [MaybeUninit<u8>]) -> Self {
224+
UninitSlice::from_uninit_slice(slice)
225+
}
226+
}
227+
182228
macro_rules! impl_index {
183229
($($t:ty),*) => {
184230
$(
@@ -187,16 +233,14 @@ macro_rules! impl_index {
187233

188234
#[inline]
189235
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) }
236+
UninitSlice::from_uninit_slice_ref(&self.0[index])
192237
}
193238
}
194239

195240
impl IndexMut<$t> for UninitSlice {
196241
#[inline]
197242
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) }
243+
UninitSlice::from_uninit_slice(&mut self.0[index])
200244
}
201245
}
202246
)*

src/bytes_mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1102,7 +1102,7 @@ unsafe impl BufMut for BytesMut {
11021102
if self.capacity() == self.len() {
11031103
self.reserve(64);
11041104
}
1105-
UninitSlice::from_slice(self.spare_capacity_mut())
1105+
self.spare_capacity_mut().into()
11061106
}
11071107

11081108
// Specialize these methods so they can skip checking `remaining_mut`

0 commit comments

Comments
 (0)