Fork of Relibc
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