1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
//! Write-only references and slices.
#![deny(
missing_docs,
clippy::all,
clippy::cargo,
clippy::missing_const_for_fn,
clippy::missing_inline_in_public_items
)]
#![no_std]
use core::marker::PhantomData;
use core::mem::MaybeUninit;
use core::ptr::NonNull;
/// A write-only reference of `T`.
pub struct OutRef<'a, T> {
data: NonNull<T>,
_marker: PhantomData<&'a mut MaybeUninit<T>>,
}
unsafe impl<T: Send> Send for OutRef<'_, T> {}
unsafe impl<T: Sync> Sync for OutRef<'_, T> {}
impl<'a, T> OutRef<'a, T> {
/// Forms an `OutRef<'a, T>`.
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `data` must be valid for writes.
///
/// * `data` must be properly aligned.
#[inline(always)]
pub unsafe fn from_raw(data: *mut T) -> Self {
Self {
data: NonNull::new_unchecked(data),
_marker: PhantomData,
}
}
/// Forms an `OutBuf` from an initialized value.
#[inline(always)]
pub fn new(val: &'a mut T) -> Self {
let data: *mut T = val;
unsafe { Self::from_raw(data) }
}
/// Forms an `OutBuf` from an uninitialized value.
#[inline(always)]
pub fn uninit(val: &'a mut MaybeUninit<T>) -> Self {
let data: *mut T = MaybeUninit::as_mut_ptr(val);
unsafe { Self::from_raw(data.cast()) }
}
/// Returns an unsafe mutable pointer to the value.
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_ptr().cast()
}
/// Sets the value of the `OutRef`.
#[inline(always)]
pub fn write(mut self, val: T) -> &'a mut T {
unsafe {
self.data.as_ptr().write(val);
self.data.as_mut()
}
}
}
/// A write-only slice of `T`.
pub struct OutBuf<'a, T> {
data: NonNull<MaybeUninit<T>>,
len: usize,
_marker: PhantomData<&'a mut [MaybeUninit<T>]>,
}
unsafe impl<T: Send> Send for OutBuf<'_, T> {}
unsafe impl<T: Sync> Sync for OutBuf<'_, T> {}
impl<'a, T> OutBuf<'a, T> {
/// Forms an `OutBuf<'a, T>`
///
/// # Safety
///
/// Behavior is undefined if any of the following conditions are violated:
///
/// * `data` must be `valid` for writes for `len * mem::size_of::<T>()` many bytes,
/// and it must be properly aligned. This means in particular:
///
/// * The entire memory range of this slice must be contained within a single allocated object!
/// Slices can never span across multiple allocated objects.
/// * `data` must be non-null and aligned even for zero-length slices. One
/// reason for this is that enum layout optimizations may rely on references
/// (including slices of any length) being aligned and non-null to distinguish
/// them from other data. You can obtain a pointer that is usable as `data`
/// for zero-length slices using `NonNull::dangling()`.
///
/// * `data` must point to `len` consecutive places for type `T`.
///
/// * The memory referenced by the returned slice must not be accessed through any other pointer
/// (not derived from the return value) for the duration of lifetime `'a`.
/// Both read and write accesses are forbidden.
///
/// * The total size `len * mem::size_of::<T>()` of the slice must be no larger than `isize::MAX`.
/// See the safety documentation of `pointer::offset`.
#[inline(always)]
pub unsafe fn from_raw(data: *mut T, len: usize) -> Self {
Self {
data: NonNull::new_unchecked(data as *mut MaybeUninit<T>),
len,
_marker: PhantomData,
}
}
/// Forms an `OutBuf` from an initialized slice.
#[inline(always)]
pub fn new(slice: &'a mut [T]) -> Self {
let len = slice.len();
let data = slice.as_mut_ptr();
unsafe { Self::from_raw(data, len) }
}
/// Forms an `OutBuf` from an uninitialized slice.
#[inline(always)]
pub fn uninit(slice: &'a mut [MaybeUninit<T>]) -> Self {
let len = slice.len();
let data = slice.as_mut_ptr();
unsafe { Self::from_raw(data.cast(), len) }
}
/// Returns true if the buffer has a length of 0.
#[inline(always)]
pub const fn is_empty(&self) -> bool {
self.len == 0
}
/// Returns the number of elements in the buffer.
#[inline(always)]
pub const fn len(&self) -> usize {
self.len
}
/// Returns an unsafe mutable pointer to the buffer.
#[inline(always)]
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_ptr().cast()
}
}