1#![deny(
3 missing_docs,
4 clippy::all,
5 clippy::cargo,
6 clippy::missing_const_for_fn,
7 clippy::missing_inline_in_public_items,
8 clippy::must_use_candidate
9)]
10#![cfg_attr(not(test), no_std)]
11
12use core::marker::PhantomData;
13use core::mem::MaybeUninit;
14use core::ptr::{self, NonNull};
15use core::slice;
16
17#[repr(transparent)]
68pub struct Out<'a, T: 'a + ?Sized> {
69 data: NonNull<T>,
70 _marker: PhantomData<&'a mut T>,
71}
72
73unsafe impl<T: Send> Send for Out<'_, T> {}
74unsafe impl<T: Sync> Sync for Out<'_, T> {}
75impl<T: Unpin> Unpin for Out<'_, T> {}
76
77impl<'a, T: ?Sized> Out<'a, T> {
78 #[inline(always)]
85 #[must_use]
86 pub unsafe fn new(data: *mut T) -> Self {
87 Self {
88 data: NonNull::new_unchecked(data),
89 _marker: PhantomData,
90 }
91 }
92
93 #[inline(always)]
98 #[must_use]
99 pub unsafe fn assume_init(mut self) -> &'a mut T {
100 self.data.as_mut()
101 }
102
103 #[inline(always)]
105 #[must_use]
106 pub fn reborrow<'s>(&'s mut self) -> Out<'s, T>
107 where
108 'a: 's,
109 {
110 Self {
111 data: self.data,
112 _marker: PhantomData,
113 }
114 }
115}
116
117impl<'a, T> Out<'a, T> {
118 #[inline(always)]
120 #[must_use]
121 pub fn from_mut(data: &'a mut T) -> Self
122 where
123 T: Copy,
124 {
125 unsafe { Self::new(data) }
126 }
127
128 #[inline(always)]
130 #[must_use]
131 pub fn from_uninit(data: &'a mut MaybeUninit<T>) -> Self {
132 let data: *mut T = MaybeUninit::as_mut_ptr(data);
133 unsafe { Self::new(data.cast()) }
134 }
135
136 #[inline(always)]
140 #[must_use]
141 pub unsafe fn into_uninit(self) -> &'a mut MaybeUninit<T> {
142 &mut *self.data.as_ptr().cast()
143 }
144
145 #[inline(always)]
147 #[must_use]
148 pub fn as_mut_ptr(&mut self) -> *mut T {
149 self.data.as_ptr().cast()
150 }
151}
152
153impl<'a, T> Out<'a, [T]> {
154 #[inline(always)]
156 #[must_use]
157 pub fn from_slice(slice: &'a mut [T]) -> Self
158 where
159 T: Copy,
160 {
161 unsafe { Self::new(slice) }
162 }
163
164 #[inline(always)]
166 #[must_use]
167 pub fn from_uninit_slice(slice: &'a mut [MaybeUninit<T>]) -> Self {
168 let slice: *mut [T] = {
169 let len = slice.len();
170 let data = slice.as_mut_ptr().cast();
171 ptr::slice_from_raw_parts_mut(data, len)
172 };
173 unsafe { Self::new(slice) }
174 }
175
176 #[inline(always)]
180 #[must_use]
181 pub unsafe fn into_uninit_slice(self) -> &'a mut [MaybeUninit<T>] {
182 let len = self.len();
183 let data = self.data.as_ptr().cast();
184 slice::from_raw_parts_mut(data, len)
185 }
186
187 #[inline(always)]
189 #[must_use]
190 pub const fn is_empty(&self) -> bool {
191 self.len() == 0
192 }
193
194 #[inline(always)]
196 #[must_use]
197 pub const fn len(&self) -> usize {
198 NonNull::len(self.data)
199 }
200
201 #[inline(always)]
203 #[must_use]
204 pub fn as_mut_ptr(&mut self) -> *mut T {
205 self.data.as_ptr().cast()
206 }
207}
208
209pub unsafe trait AsOut<T: ?Sized> {
214 fn as_out(&mut self) -> Out<'_, T>;
216}
217
218unsafe impl<T> AsOut<T> for T
219where
220 T: Copy,
221{
222 #[inline(always)]
223 #[must_use]
224 fn as_out(&mut self) -> Out<'_, T> {
225 Out::from_mut(self)
226 }
227}
228
229unsafe impl<T> AsOut<T> for MaybeUninit<T> {
230 #[inline(always)]
231 #[must_use]
232 fn as_out(&mut self) -> Out<'_, T> {
233 Out::from_uninit(self)
234 }
235}
236
237unsafe impl<T> AsOut<[T]> for [T]
238where
239 T: Copy,
240{
241 #[inline(always)]
242 #[must_use]
243 fn as_out(&mut self) -> Out<'_, [T]> {
244 Out::from_slice(self)
245 }
246}
247
248unsafe impl<T> AsOut<[T]> for [MaybeUninit<T>] {
249 #[inline(always)]
250 #[must_use]
251 fn as_out(&mut self) -> Out<'_, [T]> {
252 Out::from_uninit_slice(self)
253 }
254}
255
256#[cfg(test)]
257mod tests {
258 use super::*;
259
260 use core::{mem, ptr};
261
262 unsafe fn raw_fill_copied<T: Copy>(dst: *mut T, len: usize, val: T) {
263 if mem::size_of::<T>() == 0 {
264 return;
265 }
266
267 if len == 0 {
268 return;
269 }
270
271 if mem::size_of::<T>() == 1 {
272 let val: u8 = mem::transmute_copy(&val);
273 dst.write_bytes(val, len);
274 } else {
275 dst.write(val);
276
277 let mut n = 1;
278 while n <= len / 2 {
279 ptr::copy_nonoverlapping(dst, dst.add(n), n);
280 n *= 2;
281 }
282
283 let count = len - n;
284 if count > 0 {
285 ptr::copy_nonoverlapping(dst, dst.add(n), count);
286 }
287 }
288 }
289
290 fn fill<T: Copy>(mut buf: Out<'_, [T]>, val: T) -> &'_ mut [T] {
291 unsafe {
292 let len = buf.len();
293 let dst = buf.as_mut_ptr();
294 raw_fill_copied(dst, len, val);
295 buf.assume_init()
296 }
297 }
298
299 #[test]
300 fn fill_vec() {
301 for n in 0..128 {
302 let mut v: Vec<u32> = Vec::with_capacity(n);
303 fill(v.spare_capacity_mut().as_out(), 0x12345678);
304 unsafe { v.set_len(n) };
305 for &x in &v {
306 assert_eq!(x, 0x12345678);
307 }
308 drop(v);
309 }
310 }
311}