at master 7.8 kB view raw
1//! Wrapper for the "out pointer" pattern. 2//! 3//! This is functionally equivalent to `&Cell<MaybeUninit<T>>` except the only allowed operation is 4//! to write a `T`. Using `MaybeUninit` directly would not have been equally general; a 5//! `&mut MaybeUninit<T>` could never then be created from a `&mut T` and passed to safe code, 6//! which can safely replace it with `MaybeUninit::uninit` and make the existence of `&mut T` UB. 7//! 8//! As for the "`&Cell<...>`", this is to be slightly weaker than Rust's normally strict 9//! requirement that `&mut` references are never aliased, which can typically not be assumed when 10//! getting pointers from C. 11 12use core::{cell::UnsafeCell, fmt, marker::PhantomData, mem::MaybeUninit, ptr::NonNull}; 13 14/// Wrapper for write-only "out pointers" that are safe to write to 15// TODO: We may want to change this to &mut MaybeUninit, or have a generic parameter deciding 16// whether it should be noalias or not 17#[derive(Eq, Hash, Ord, PartialEq, PartialOrd)] 18pub struct Out<'a, T: ?Sized> { 19 ptr: NonNull<T>, 20 _marker: PhantomData<&'a UnsafeCell<T>>, 21} 22impl<'a, T: ?Sized> Out<'a, T> { 23 /// # Safety 24 /// 25 /// - pointer must either be NULL, or be valid for the duration of lifetime `'a` 26 #[inline] 27 pub unsafe fn nullable(ptr: *mut T) -> Option<Self> { 28 Some(Self { 29 ptr: NonNull::new(ptr)?, 30 _marker: PhantomData, 31 }) 32 } 33 /// # Safety 34 /// 35 /// - pointer must be valid for the duration of lifetime `'a` 36 #[inline] 37 pub unsafe fn nonnull(ptr: *mut T) -> Self { 38 if cfg!(debug_assertions) { 39 assert!(!ptr.is_null()); 40 } 41 Self { 42 ptr: NonNull::new_unchecked(ptr), 43 _marker: PhantomData, 44 } 45 } 46 #[inline] 47 pub fn from_mut(r: &'a mut T) -> Self { 48 // SAFETY: 49 // 50 // - `r` will obviously have the same lifetime as Self 51 // - a Rust reference is obviously valid as a pointer, and the lifetime is tied to that of 52 // this struct 53 unsafe { Self::nonnull(r) } 54 } 55 #[inline] 56 pub fn as_mut_ptr(&mut self) -> *mut T { 57 self.ptr.as_ptr() 58 } 59} 60impl<'a, T> Out<'a, T> { 61 #[inline] 62 pub fn from_uninit_mut(r: &'a mut MaybeUninit<T>) -> Self { 63 // SAFETY: 64 // 65 // Same as for from_mut. It's fine if *r is uninitialized, as this wrapper only allows 66 // writes. 67 unsafe { Self::nonnull(r.as_mut_ptr()) } 68 } 69 #[inline] 70 pub fn write(&mut self, t: T) { 71 unsafe { 72 self.ptr.as_ptr().write(t); 73 } 74 } 75} 76impl<'a, T, const N: usize> Out<'a, [T; N]> { 77 #[inline] 78 pub fn as_slice_mut<'b>(&'b mut self) -> Out<'b, [T]> { 79 unsafe { 80 let ptr: *mut [T; N] = self.as_mut_ptr(); 81 Out::from_raw_parts(ptr.cast::<T>(), N) 82 } 83 } 84} 85impl<'a, T> Out<'a, [T]> { 86 /// # Safety 87 /// 88 /// If `len > 0`, `ptr` be valid for `len` elements of `T`, during lifetime `'a`. 89 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self { 90 // Empty slices must be non-NULL in Rust, but C typically does not force this for 91 // pointer-length pairs. 92 let ptr = if len == 0 { 93 core::ptr::dangling_mut::<T>() 94 } else { 95 ptr 96 }; 97 Self::nonnull(core::slice::from_raw_parts_mut(ptr, len)) 98 } 99 pub fn len(&self) -> usize { 100 self.ptr.as_ptr().len() 101 } 102 pub fn is_empty(&self) -> bool { 103 self.len() == 0 104 } 105 // TODO: Maybe strengthen lifetimes? 106 #[inline] 107 pub fn split_at_checked<'b>(&'b mut self, n: usize) -> Option<[Out<'b, [T]>; 2]> { 108 let l = self.ptr.len(); 109 if n > l { 110 return None; 111 } 112 Some([ 113 Out { 114 ptr: unsafe { 115 NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( 116 self.ptr.as_mut_ptr(), 117 n, 118 )) 119 }, 120 _marker: PhantomData, 121 }, 122 Out { 123 ptr: unsafe { 124 NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( 125 self.ptr.as_mut_ptr().add(n), 126 l - n, 127 )) 128 }, 129 _marker: PhantomData, 130 }, 131 ]) 132 } 133 #[inline] 134 pub fn copy_from_slice(&mut self, src: &[T]) 135 where 136 T: Copy, 137 { 138 assert_eq!( 139 self.ptr.len(), 140 src.len(), 141 "Out::copy_from_slice size mismatch" 142 ); 143 unsafe { 144 // SAFETY: 145 // 146 // - we have already know from the existence of self that the slice is a valid writable 147 // pointer 148 // - src is similarly also a valid readable pointer of the same type 149 // - because of `T: Copy`, it is valid to copy bytes directly 150 // - although self.ptr may alias, src must not alias with any writable pointer, and the 151 // Copy bound ensures T cannot have interior mutability since `UnsafeCell: !Copy` 152 self.ptr 153 .as_mut_ptr() 154 .copy_from_nonoverlapping(src.as_ptr(), src.len()); 155 } 156 } 157 pub fn copy_common_length_from_slice(&mut self, src: &[T]) -> usize 158 where 159 T: Copy, 160 { 161 let l = src.len().min(self.len()); 162 self.split_at_checked(l).unwrap()[0].copy_from_slice(&src[..l]); 163 l 164 } 165 // TODO: better API, impl RangeBounds, also fn get(usize) -> Out<T> 166 pub fn subslice<'b>(&'b mut self, start: usize, end: usize) -> Out<[T]> { 167 assert!(start <= end); 168 assert!(end <= self.len()); 169 unsafe { Self::from_raw_parts(self.as_mut_ptr().as_mut_ptr().add(start), end - start) } 170 } 171 pub fn index<'b>(&'b mut self, i: usize) -> Out<T> { 172 assert!(i <= self.len()); 173 unsafe { Out::nonnull(self.as_mut_ptr().as_mut_ptr().add(i)) } 174 } 175} 176// TODO: use bytemuck 177impl<T: plain::Plain> Out<'_, [T]> { 178 pub fn zero(&mut self) { 179 let l = self.ptr.len(); 180 unsafe { 181 // SAFETY: 182 // - already know the pointer is valid up to its length 183 // - the Plain trait ensures zero is a valid bit pattern 184 self.ptr.as_mut_ptr().write_bytes(0, l) 185 } 186 } 187 #[inline] 188 pub fn cast_slice_to<'b, U>(mut self) -> Out<'b, [U]> 189 where 190 T: CastSlice<U>, 191 { 192 assert_eq!(self.as_mut_ptr().as_mut_ptr() as usize % align_of::<U>(), 0); 193 194 let byte_length = self.as_mut_ptr().len() * size_of::<T>(); 195 196 unsafe { 197 Out::from_raw_parts( 198 self.as_mut_ptr().as_mut_ptr().cast(), 199 byte_length / size_of::<U>(), 200 ) 201 } 202 } 203} 204// TODO: use bytemuck 205pub unsafe trait CastSlice<U> {} 206unsafe impl CastSlice<i8> for u8 {} 207unsafe impl CastSlice<u8> for i8 {} 208 209impl<T: ?Sized> fmt::Pointer for Out<'_, T> { 210 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 211 write!(f, "{:p}", self.ptr) 212 } 213} 214impl<T: ?Sized> fmt::Debug for Out<'_, T> { 215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 216 write!(f, "[Out: {:p}]", self.ptr) 217 } 218} 219/// Marker trait for types where it is sound to turn `Out<struct { ... }>` into `struct { ...: 220/// Out<...> }` by simply referencing fields. This is safe for any struct but must not be 221/// implemented for `Deref` types so that `Out<&struct { ... }>` is never projected in a way that 222/// adds mutability. 223pub unsafe trait OutProject {} 224 225impl<'a, T: ?Sized> Out<'a, T> { 226 pub unsafe fn with_lifetime_of<'b, U: ?Sized>(mut self, u: &'b U) -> Out<'b, T> { 227 Out::nonnull(self.as_mut_ptr()) 228 } 229} 230 231// TODO: unit tests