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)]
36pub struct Out<'a, T: 'a + ?Sized> {
37 data: NonNull<T>,
38 _marker: PhantomData<&'a mut T>,
39}
40
41unsafe impl<T: Send> Send for Out<'_, T> {}
42unsafe impl<T: Sync> Sync for Out<'_, T> {}
43impl<T: Unpin> Unpin for Out<'_, T> {}
44
45impl<'a, T: ?Sized> Out<'a, T> {
46 #[inline(always)]
53 #[must_use]
54 pub unsafe fn new(data: *mut T) -> Self {
55 Self {
56 data: NonNull::new_unchecked(data),
57 _marker: PhantomData,
58 }
59 }
60
61 #[inline(always)]
66 #[must_use]
67 pub unsafe fn assume_init(mut self) -> &'a mut T {
68 self.data.as_mut()
69 }
70
71 #[inline(always)]
73 #[must_use]
74 pub fn reborrow<'s>(&'s mut self) -> Out<'s, T>
75 where
76 'a: 's,
77 {
78 Self {
79 data: self.data,
80 _marker: PhantomData,
81 }
82 }
83}
84
85impl<'a, T> Out<'a, T> {
86 #[inline(always)]
88 #[must_use]
89 pub fn from_mut(data: &'a mut T) -> Self
90 where
91 T: Copy,
92 {
93 unsafe { Self::new(data) }
94 }
95
96 #[inline(always)]
98 #[must_use]
99 pub fn from_uninit(data: &'a mut MaybeUninit<T>) -> Self {
100 let data: *mut T = MaybeUninit::as_mut_ptr(data);
101 unsafe { Self::new(data.cast()) }
102 }
103
104 #[inline(always)]
108 #[must_use]
109 pub unsafe fn into_uninit(self) -> &'a mut MaybeUninit<T> {
110 &mut *self.data.as_ptr().cast()
111 }
112
113 #[inline(always)]
115 #[must_use]
116 pub fn as_mut_ptr(&mut self) -> *mut T {
117 self.data.as_ptr().cast()
118 }
119}
120
121impl<'a, T> Out<'a, [T]> {
122 #[inline(always)]
124 #[must_use]
125 pub fn from_slice(slice: &'a mut [T]) -> Self
126 where
127 T: Copy,
128 {
129 unsafe { Self::new(slice) }
130 }
131
132 #[inline(always)]
134 #[must_use]
135 pub fn from_uninit_slice(slice: &'a mut [MaybeUninit<T>]) -> Self {
136 let slice: *mut [T] = {
137 let len = slice.len();
138 let data = slice.as_mut_ptr().cast();
139 ptr::slice_from_raw_parts_mut(data, len)
140 };
141 unsafe { Self::new(slice) }
142 }
143
144 #[inline(always)]
148 #[must_use]
149 pub unsafe fn into_uninit_slice(self) -> &'a mut [MaybeUninit<T>] {
150 let len = self.len();
151 let data = self.data.as_ptr().cast();
152 unsafe { slice::from_raw_parts_mut(data, len) }
153 }
154
155 #[inline(always)]
157 #[must_use]
158 pub const fn is_empty(&self) -> bool {
159 self.len() == 0
160 }
161
162 #[inline(always)]
164 #[must_use]
165 pub const fn len(&self) -> usize {
166 NonNull::len(self.data)
167 }
168
169 #[inline(always)]
171 #[must_use]
172 pub fn as_mut_ptr(&mut self) -> *mut T {
173 self.data.as_ptr().cast()
174 }
175}
176
177pub unsafe trait AsOut<T: ?Sized> {
182 fn as_out(&mut self) -> Out<'_, T>;
184}
185
186unsafe impl<T> AsOut<T> for T
187where
188 T: Copy,
189{
190 #[inline(always)]
191 #[must_use]
192 fn as_out(&mut self) -> Out<'_, T> {
193 Out::from_mut(self)
194 }
195}
196
197unsafe impl<T> AsOut<T> for MaybeUninit<T> {
198 #[inline(always)]
199 #[must_use]
200 fn as_out(&mut self) -> Out<'_, T> {
201 Out::from_uninit(self)
202 }
203}
204
205unsafe impl<T> AsOut<[T]> for [T]
206where
207 T: Copy,
208{
209 #[inline(always)]
210 #[must_use]
211 fn as_out(&mut self) -> Out<'_, [T]> {
212 Out::from_slice(self)
213 }
214}
215
216unsafe impl<T> AsOut<[T]> for [MaybeUninit<T>] {
217 #[inline(always)]
218 #[must_use]
219 fn as_out(&mut self) -> Out<'_, [T]> {
220 Out::from_uninit_slice(self)
221 }
222}
223
224#[cfg(test)]
225mod tests {
226 use super::*;
227
228 use core::{mem, ptr};
229
230 unsafe fn raw_fill_copied<T: Copy>(dst: *mut T, len: usize, val: T) {
231 if mem::size_of::<T>() == 0 {
232 return;
233 }
234
235 if len == 0 {
236 return;
237 }
238
239 if mem::size_of::<T>() == 1 {
240 let val: u8 = mem::transmute_copy(&val);
241 dst.write_bytes(val, len);
242 } else {
243 dst.write(val);
244
245 let mut n = 1;
246 while n <= len / 2 {
247 ptr::copy_nonoverlapping(dst, dst.add(n), n);
248 n *= 2;
249 }
250
251 let count = len - n;
252 if count > 0 {
253 ptr::copy_nonoverlapping(dst, dst.add(n), count);
254 }
255 }
256 }
257
258 fn fill<T: Copy>(mut buf: Out<'_, [T]>, val: T) -> &'_ mut [T] {
259 unsafe {
260 let len = buf.len();
261 let dst = buf.as_mut_ptr();
262 raw_fill_copied(dst, len, val);
263 buf.assume_init()
264 }
265 }
266
267 #[test]
268 fn fill_vec() {
269 for n in 0..128 {
270 let mut v: Vec<u32> = Vec::with_capacity(n);
271 fill(v.spare_capacity_mut().as_out(), 0x12345678);
272 unsafe { v.set_len(n) };
273 for &x in &v {
274 assert_eq!(x, 0x12345678);
275 }
276 drop(v);
277 }
278 }
279}