mirror of
https://github.com/tokio-rs/bytes.git
synced 2026-08-29 00:00:15 +02:00
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
This commit is contained in:
+50
-6
@@ -22,10 +22,44 @@ use core::ops::{
|
|||||||
pub struct UninitSlice([MaybeUninit<u8>]);
|
pub struct UninitSlice([MaybeUninit<u8>]);
|
||||||
|
|
||||||
impl UninitSlice {
|
impl UninitSlice {
|
||||||
pub(crate) fn from_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice {
|
/// Creates a `&mut UninitSlice` wrapping slice of uninitialised memory.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use bytes::buf::UninitSlice;
|
||||||
|
/// use core::mem::MaybeUninit;
|
||||||
|
///
|
||||||
|
/// let mut buffer = [MaybeUninit::uninit(); 64];
|
||||||
|
/// let slice = UninitSlice::from_uninit_slice(&mut buffer[..]);
|
||||||
|
///
|
||||||
|
/// let mut vec = Vec::with_capacity(1024);
|
||||||
|
/// let spare: &mut UninitSlice = vec.spare_capacity_mut().into();
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn from_uninit_slice(slice: &mut [MaybeUninit<u8>]) -> &mut UninitSlice {
|
||||||
unsafe { &mut *(slice as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
|
unsafe { &mut *(slice as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn from_uninit_slice_ref(slice: &[MaybeUninit<u8>]) -> &UninitSlice {
|
||||||
|
unsafe { &*(slice as *const [MaybeUninit<u8>] as *const UninitSlice) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a `&mut UninitSlice` wrapping slice of initialised memory.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// use bytes::buf::UninitSlice;
|
||||||
|
///
|
||||||
|
/// let mut buffer = [0u8; 64];
|
||||||
|
/// let slice = UninitSlice::from_slice(&mut buffer[..]);
|
||||||
|
/// ```
|
||||||
|
#[inline]
|
||||||
|
pub fn from_slice(slice: &mut [u8]) -> &mut UninitSlice {
|
||||||
|
unsafe { &mut *(slice as *mut [u8] as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
|
||||||
|
}
|
||||||
|
|
||||||
/// Create a `&mut UninitSlice` from a pointer and a length.
|
/// Create a `&mut UninitSlice` from a pointer and a length.
|
||||||
///
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@@ -48,7 +82,7 @@ impl UninitSlice {
|
|||||||
pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
|
pub unsafe fn from_raw_parts_mut<'a>(ptr: *mut u8, len: usize) -> &'a mut UninitSlice {
|
||||||
let maybe_init: &mut [MaybeUninit<u8>] =
|
let maybe_init: &mut [MaybeUninit<u8>] =
|
||||||
core::slice::from_raw_parts_mut(ptr as *mut _, len);
|
core::slice::from_raw_parts_mut(ptr as *mut _, len);
|
||||||
Self::from_slice(maybe_init)
|
Self::from_uninit_slice(maybe_init)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Write a single byte at the specified offset.
|
/// Write a single byte at the specified offset.
|
||||||
@@ -179,6 +213,18 @@ impl fmt::Debug for UninitSlice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a mut [u8]> for &'a mut UninitSlice {
|
||||||
|
fn from(slice: &'a mut [u8]) -> Self {
|
||||||
|
UninitSlice::from_slice(slice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&'a mut [MaybeUninit<u8>]> for &'a mut UninitSlice {
|
||||||
|
fn from(slice: &'a mut [MaybeUninit<u8>]) -> Self {
|
||||||
|
UninitSlice::from_uninit_slice(slice)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! impl_index {
|
macro_rules! impl_index {
|
||||||
($($t:ty),*) => {
|
($($t:ty),*) => {
|
||||||
$(
|
$(
|
||||||
@@ -187,16 +233,14 @@ macro_rules! impl_index {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: $t) -> &UninitSlice {
|
fn index(&self, index: $t) -> &UninitSlice {
|
||||||
let maybe_uninit: &[MaybeUninit<u8>] = &self.0[index];
|
UninitSlice::from_uninit_slice_ref(&self.0[index])
|
||||||
unsafe { &*(maybe_uninit as *const [MaybeUninit<u8>] as *const UninitSlice) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IndexMut<$t> for UninitSlice {
|
impl IndexMut<$t> for UninitSlice {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index_mut(&mut self, index: $t) -> &mut UninitSlice {
|
fn index_mut(&mut self, index: $t) -> &mut UninitSlice {
|
||||||
let maybe_uninit: &mut [MaybeUninit<u8>] = &mut self.0[index];
|
UninitSlice::from_uninit_slice(&mut self.0[index])
|
||||||
unsafe { &mut *(maybe_uninit as *mut [MaybeUninit<u8>] as *mut UninitSlice) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
|||||||
+1
-1
@@ -1102,7 +1102,7 @@ unsafe impl BufMut for BytesMut {
|
|||||||
if self.capacity() == self.len() {
|
if self.capacity() == self.len() {
|
||||||
self.reserve(64);
|
self.reserve(64);
|
||||||
}
|
}
|
||||||
UninitSlice::from_slice(self.spare_capacity_mut())
|
self.spare_capacity_mut().into()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specialize these methods so they can skip checking `remaining_mut`
|
// Specialize these methods so they can skip checking `remaining_mut`
|
||||||
|
|||||||
Reference in New Issue
Block a user