without_alloc/
uninit.rs

1//! Safe abstractions around pointing at uninitialized memory without references.
2//!
3//! This solves two issues beyond the standard library: Firstly, `MaybeUninit` does not permitted
4//! unsized types. Secondly, a strict interpretation of pointer provenance implies that once a
5//! reference is created our access is restricted the memory referred to in it. This spoils our
6//! access to any memory in a potential tail of the allocation, which is wasteful.
7//!
8//! It is potentially **UB** to have references to uninitialized memory even if such a reference is
9//! not 'used' in any particular manner. See [the discussion of the unsafe working group][wg-ref].
10//!
11//! TODO: In some next version we'd like to switch to `&'a UnsafeCell<MaybeUninit<T>>` here, or
12//! even replace the UnsafeCell once we've replace the `view` attribute in Uninit. But alas we're
13//! not permitted to have an unsized parameter to `MaybeUninit`.
14//!
15//! More work using unsized type parameter would in particular make it redundant to store the
16//! length as we could refer to memory with a wrapper `Byte(u8)` and the `T = [Byte]` instantiation
17//! for the type parameter of `Uninit`/`UninitView`. Storing additional bytes would be a wrapper
18//! around the main interface.
19//!
20//! [wg-ref]: https://github.com/rust-lang/unsafe-code-guidelines/issues/77
21use core::{fmt, mem, slice, ptr};
22use core::alloc::Layout;
23use core::marker::PhantomData;
24
25use crate::boxed::Box;
26use unsize::CoerciblePtr;
27
28/// Points to an uninitialized place but would otherwise be a valid reference.
29///
30/// This is a `&mut`-like struct that is somewhat of a pendant to `MaybeUninit`. It makes it
31/// possible to deal with uninitialized allocations without requiring an `unsafe` block
32/// initializing them and offers a much safer interface for partial initialization and layout
33/// calculations than raw pointers.
34///
35/// Note that it also supports slices which means it does not use `MaybeUninit` internally but
36/// offers conversion where necessary.
37///
38/// ## Usage
39///
40/// The basic usage is also interacting with `MaybeUninit`:
41///
42/// ```
43/// # #[derive(Default)]
44/// # struct MyStruct { };
45/// use core::mem::MaybeUninit;
46/// use without_alloc::Uninit;
47///
48/// let mut alloc: MaybeUninit<MyStruct> = MaybeUninit::uninit();
49/// let uninit = Uninit::from_maybe_uninit(&mut alloc);
50///
51/// // notice: no unsafe
52/// let instance: &mut MyStruct = uninit.init(MyStruct::default());
53/// ```
54///
55/// But since we are working on arbitrary uninitialized memory it is also possible to reuse the
56/// structure for completely arbitrary other types. Just note that there is no integrated mechanis
57/// for calling `Drop`.
58///
59/// ```
60/// use core::mem::MaybeUninit;
61/// use without_alloc::Uninit;
62///
63/// // Just a generic buffer.
64/// let mut alloc: MaybeUninit<[u32; 1024]> = MaybeUninit::uninit();
65/// let uninit = Uninit::from_maybe_uninit(&mut alloc);
66///
67/// // Now use the first `u32` for a counter:
68/// let mut counter = uninit.cast().unwrap();
69/// let mut tail = counter.split_to_fit();
70/// let counter: &mut u32 = counter.init(0);
71///
72/// // And some more for a few `u64`.
73/// // Note that these are not trivially aligned, but `Uninit` does that for us.
74/// let mut values = tail.split_cast().unwrap();
75/// // No more use, so don't bother with `split_to_fit` and just `init`.
76/// let values: &mut [u64; 2] = values.init([0xdead, 0xbeef]);
77/// ```
78#[must_use = "This is a pointer-like type that has no effect on its own. Use `init` to insert a value."]
79pub struct Uninit<'a, T: ?Sized> {
80    /// The underlying view.
81    ///
82    /// Uninit additional imposes on it that the underlying memory is mutable.
83    view: UninitView<'a, T>,
84
85    /// Reminder for every construction.
86    mutable: PhantomData<&'a mut ()>,
87}
88
89/// A non-mutable view on a region used in an [`Uninit`].
90///
91/// Makes it possible to utilize the traversal methods (`split*`, `cast*`, ..) without requiring a
92/// mutable reference to the original `Uninit`. It will also never expose mutable pointers or
93/// accidentally offer an aliased mutable reference. Prefer this to instead avoiding the borrow of
94/// the `Uninit` and manually managing pointers to the region.
95///
96/// [`Uninit`]: ./struct.Uninit.html
97#[must_use = "This is a pointer-like type that has no effect on its own."]
98pub struct UninitView<'a, T: ?Sized> {
99    /// Pointer to the start of the region.
100    ///
101    /// Note that `len` is always at least as large as the (minimum) size of `T`. Furthermore, the
102    /// pointer is always correctly aligned to a `T`.
103    ptr: ptr::NonNull<T>,
104
105    /// The actual length *in bytes*.
106    ///
107    /// May be larger than required.
108    len: usize,
109
110    /// Virtual lifetime to make this behave more similar to references.
111    ///
112    /// This borrows structures that hand out `Uninit` allocations.
113    lifetime: PhantomData<&'a ()>,
114
115    /// We'll be holding an actual `NonNull<T>` in the future (when dynamically sized pointers to
116    /// slices are more ergonomic). For now, just type ourselves.
117    typed: PhantomData<*mut T>,
118}
119
120impl Uninit<'_, ()> {
121    /// Create a uninit pointer from raw memory.
122    ///
123    /// ## Safety
124    /// A valid allocation must exist at the pointer with length at least `len`. There must be *no*
125    /// references aliasing the memory location, and it must be valid to write uninitialized bytes
126    /// into arbitrary locations of the region.
127    ///
128    /// In particular, it is **UB** to create this from a reference to a variable of a type for
129    /// which a completely uninitialized content is not valid. The standard type for avoiding the
130    /// UB is `core::mem::MaybeUninit`.
131    ///
132    /// When in doubt, refactor code such that utilization of `from_maybe_uninit` is possible.
133    pub unsafe fn from_memory(ptr: ptr::NonNull<u8>, len: usize) -> Self {
134        Uninit::from_presumed_mutable_view(UninitView {
135            ptr: ptr.cast(),
136            len,
137            lifetime: PhantomData,
138            typed: PhantomData,
139        })
140    }
141
142    /// Split so that the second part fits the layout.
143    ///
144    /// Return `Ok` if this is possible in-bounds and `Err` if it is not.
145    pub fn split_layout(&mut self, layout: Layout) -> Option<Self> {
146        self.view.split_layout(layout)
147            .map(Self::from_presumed_mutable_view)
148    }
149}
150
151impl<'a> Uninit<'a, ()> {
152    fn decast<T: ?Sized>(uninit: Uninit<'a, T>) -> Self {
153        Uninit::from_presumed_mutable_view(UninitView {
154            ptr: uninit.view.ptr.cast(),
155            len: uninit.view.len,
156            lifetime: PhantomData,
157            typed: PhantomData,
158        })
159    }
160
161    /// Split so that the tail is aligned and valid for a `U`.
162    ///
163    /// Return `Ok` if this is possible in-bounds (aligned and enough room for at least one `U`)
164    /// and `Err` if it is not. The first tuple element is the `Uninit` pointing to the skipped
165    /// memory.
166    pub fn split_cast<U>(&mut self) -> Option<Uninit<'a, U>> {
167        let split = self.split_layout(Layout::new::<U>())?;
168        let cast = split.cast::<U>().unwrap();
169        Some(cast)
170    }
171
172    /// Split so that the tail is aligned for a slice `[U]`.
173    ///
174    /// Return `Ok` if this is possible in-bounds and `Err` if it is not. The first tuple element
175    /// is the `Uninit` pointing to the skipped memory.
176    ///
177    /// The length of the slice is the arbitrary amount that fits into the tail of the allocation.
178    /// Note that the length always fulfills the safety requirements for `slice::from_raw_parts`
179    /// since the `Uninit` must be contained in a single allocation.
180    pub fn split_slice<U>(&mut self) -> Option<Uninit<'a, [U]>> {
181        let layout = Layout::for_value::<[U]>(&[]);
182        let split = self.split_layout(layout)?;
183        let cast = split.cast_slice::<U>().unwrap();
184        Some(cast)
185    }
186}
187
188impl<T> Uninit<'_, T> {
189    /// Invent a new uninit allocation for a zero-sized type (ZST).
190    ///
191    /// # Panics
192    /// This method panics when the type parameter is not a zero sized type.
193    pub fn invent_for_zst() -> Self {
194        // SAFETY: zst is always unaliased.
195        unsafe { Uninit::from_view(UninitView::invent_for_zst()) }
196    }
197}
198
199impl<'a, T> Uninit<'a, T> {
200    /// Create an `uninit` from a view.
201    ///
202    /// ## Safety
203    /// The caller must prove that the pointed-to memory is mutable and that it is unaliased.
204    pub unsafe fn from_view(view: UninitView<'a, T>) -> Self {
205        Self::from_presumed_mutable_view(view)
206    }
207
208    /// Create an initializable pointer to the inner bytes of a `MaybeUninit`.
209    pub fn from_maybe_uninit(mem: &'a mut mem::MaybeUninit<T>) -> Self {
210        let ptr = ptr::NonNull::new(mem.as_mut_ptr()).unwrap();
211        let raw = unsafe {
212            // SAFETY:
213            // * unaliased as we had a mutable reference
214            // * can write uninitialized bytes as much as we want
215            Uninit::from_memory(ptr.cast(), mem::size_of_val(mem))
216        };
217        raw.cast().unwrap()
218    }
219
220    /// Split the uninit slice at a byte boundary.
221    ///
222    /// Return `Ok` if the location is in-bounds and `Err` if it is out of bounds.
223    pub fn split_at_byte(&mut self, at: usize) -> Option<Uninit<'a, ()>> {
224        self.view.split_at_byte(at)
225            .map(Uninit::from_presumed_mutable_view)
226    }
227
228    /// Try to cast to an `Uninit` for another type.
229    ///
230    /// Return `Ok` if the current `Uninit` is suitably aligned and large enough to hold at least
231    /// one `U` and `Err` if it is not. Note that the successful result points to unused remaining
232    /// memory behind where the instance can be placed.
233    ///
234    /// Use [`split_to_fit`] to get rid of surplus memory at the end.
235    ///
236    /// [`split_to_fit`]: #method.split_to_fit
237    pub fn cast<U>(self) -> Result<Uninit<'a, U>, Self> {
238        self.view.cast()
239            .map(Uninit::from_presumed_mutable_view)
240            .map_err(Self::from_presumed_mutable_view)
241    }
242
243    /// Try to cast to an `Uninit` for a slice type.
244    ///
245    /// Return `Ok` if the current `Uninit` is suitably aligned and large enough to hold at least
246    /// one `U` and `Err` if it is not. Note that the successful result points to unused remaining
247    /// memory behind where the instances can be placed.
248    pub fn cast_slice<U>(self) -> Result<Uninit<'a, [U]>, Self> {
249        self.view.cast_slice::<U>()
250            .map(Uninit::from_presumed_mutable_view)
251            .map_err(Self::from_presumed_mutable_view)
252    }
253
254    /// Split off the tail that is not required for holding an instance of `T`.
255    ///
256    /// This operation is idempotent.
257    pub fn split_to_fit(&mut self) -> Uninit<'a, ()> {
258        self.split_at_byte(mem::size_of::<T>()).unwrap()
259    }
260}
261
262
263impl<'a, T: ?Sized> Uninit<'a, T> {
264    /// Acquires the underlying *mut pointer.
265    pub const fn as_ptr(&self) -> *mut T {
266        self.view.ptr.as_ptr()
267    }
268
269    /// Acquires the underlying pointer as a `NonNull`.
270    pub const fn as_non_null(&self) -> ptr::NonNull<T> {
271        self.view.ptr
272    }
273
274    /// Dereferences the content.
275    ///
276    /// The resulting lifetime is bound to self so this behaves "as if" it were actually an
277    /// instance of T that is getting borrowed. If a longer lifetime is needed, use `into_ref`.
278    ///
279    /// # Safety
280    /// The pointee must have been initialized through other means.
281    pub unsafe fn as_ref(&self) -> &T {
282        self.view.as_ref()
283    }
284
285    /// Mutably dereferences the content.
286    ///
287    /// The resulting lifetime is bound to self so this behaves "as if" it were actually an
288    /// instance of T that is getting borrowed. If a longer lifetime is needed, use `into_mut`.
289    ///
290    /// # Safety
291    /// The pointee must have been initialized through other means.
292    pub unsafe fn as_mut(&mut self) -> &mut T {
293        &mut *self.as_ptr()
294    }
295
296    /// Turn this into a reference to the content.
297    ///
298    /// # Safety
299    /// The pointee must have been initialized through other means.
300    pub unsafe fn into_ref(self) -> &'a T {
301        &*self.as_ptr()
302    }
303
304    /// Turn this into a mutable reference to the content.
305    ///
306    /// # Safety
307    /// The pointee must have been initialized through other means.
308    pub unsafe fn into_mut(self) -> &'a mut T {
309        &mut *self.as_ptr()
310    }
311}
312
313impl<'a, T> Uninit<'a, T> {
314    /// Initialize the place and return a reference to the value.
315    pub fn init(self, val: T) -> &'a mut T {
316        let ptr = self.as_ptr();
317        unsafe {
318            // SAFETY:
319            // * can only create instances where layout of `T` 'fits'
320            // * valid for lifetime `'a` (as per `UninitView`).
321            // * unaliased for lifetime `'a` (as per own invariant from unsafe constructor). No
322            //   other method duplicates the pointer or allows a second `Uninit` without borrowing
323            //   the first.
324            ptr::write(ptr, val);
325            &mut *ptr
326        }
327    }
328
329    /// Turn this into a reference to standard `MaybeUninit`.
330    ///
331    /// This is mainly useful for interfacing with other consumers which expect standard library
332    /// types. It may also improve ergonomics for writing to the pointee partially initialized
333    /// instances of `T` that are obtained via other means.
334    ///
335    /// Note that the sequence `from_maybe_uninit`, `into_maybe_uninit` is a no-op. The converse is
336    /// however not the case, as it will potentially discard unused padding present in the original
337    /// `Uninit`.
338    pub fn into_maybe_uninit(self) -> &'a mut mem::MaybeUninit<T> {
339        // SAFETY: MaybeUninit is a transparent wrapper and need not be initialized.
340        unsafe { &mut*(self.as_ptr() as *mut mem::MaybeUninit<T>) }
341    }
342
343    /// Read a value from the uninit place without moving it.
344    ///
345    /// The `Uninit` ensures that the inner pointer is correctly aligned, non-null, and points to a
346    /// large enough region for reading a `T`.
347    ///
348    /// ## Safety
349    /// Caller must ensure that the memory is initialized as a valid `T`. It must also avoid double
350    /// `Drop`. Basically, a new instance is created.
351    pub unsafe fn read(&self) -> T {
352        ptr::read(self.as_ptr())
353    }
354
355    /// Utilize this `Uninit` allocation for a boxed value.
356    ///
357    /// Stores the value at the pointed-to location and utilizes the `Box` as a RAII-guard to
358    /// properly drop the value when the box itself is dropped.
359    pub fn into_box(self, val: T) -> Box<'a, T> {
360        Box::new(val, self)
361    }
362}
363
364impl<'a, T> Uninit<'a, [T]> {
365    /// Creates a pointer to an empty slice.
366    pub fn empty() -> Self {
367        Uninit::from_presumed_mutable_view(UninitView {
368            ptr: {
369                let base = ptr::NonNull::<T>::dangling().as_ptr();
370                let slice = ptr::slice_from_raw_parts_mut(base, 0);
371                ptr::NonNull::new(slice).unwrap()
372            },
373            len: 0,
374            lifetime: PhantomData,
375            typed: PhantomData,
376        })
377    }
378
379    /// Create an initializable pointer to the inner bytes of a `MaybeUninit`.
380    pub fn from_maybe_uninit_slice(mem: &'a mut [mem::MaybeUninit<T>]) -> Self {
381        let size = mem::size_of_val(mem);
382        let ptr = ptr::NonNull::from(mem);
383        let raw = unsafe {
384            // SAFETY:
385            // * unaliased as we had a mutable reference
386            // * can write uninitialized bytes as much as we want
387            Uninit::from_memory(ptr.cast(), size)
388        };
389        raw.cast_slice().unwrap()
390    }
391
392    /// Get the pointer to the first element of the slice.
393    ///
394    /// If the slice would be empty then the pointer may be the past-the-end pointer as well.
395    pub const fn as_begin_ptr(&self) -> *mut T {
396        self.view.ptr.as_ptr() as *mut T
397    }
398
399    /// Calculate the theoretical capacity of a slice in the pointed-to allocation.
400    pub fn capacity(&self) -> usize {
401        self.view.capacity()
402    }
403
404    /// Split the slice at an index.
405    ///
406    /// This is the pointer equivalent of `slice::split_at`.
407    pub fn split_at(&mut self, at: usize) -> Option<Self> {
408        self.view.split_at(at)
409            .map(Self::from_presumed_mutable_view)
410    }
411
412    /// Get the trailing bytes behind the slice.
413    ///
414    /// The underlying allocation need not be a multiple of the slice element size which may leave
415    /// unusable bytes. This splits these unusable bytes into an untyped `Uninit` which can be
416    /// reused arbitrarily.
417    ///
418    /// This operation is idempotent.
419    pub fn shrink_to_fit(&mut self) -> Uninit<'a, ()> {
420        Uninit::decast(self.split_at(self.capacity()).unwrap())
421    }
422
423    /// Split the first element from the slice.
424    ///
425    /// This is the pointer equivalent of `slice::split_first`.
426    pub fn split_first(&mut self) -> Option<Uninit<'a, T>> {
427        let mut part = self.split_at(1)?;
428        // Now we are the first part, but we wanted the first to be split off.
429        mem::swap(self, &mut part);
430        // If it is a valid slice of length 1 it is a valid `T`.
431        Some(Uninit::decast(part).cast().unwrap())
432    }
433
434    /// Split the last element from the slice.
435    ///
436    /// This is the pointer equivalent of `slice::split_last`.
437    pub fn split_last(&mut self) -> Option<Uninit<'a, T>> {
438        // Explicitely wrap here: If capacity is 0 then `0 < size_of::<T> ` and the split will fail.
439        let split = self.capacity().wrapping_sub(1);
440        let part = self.split_at(split)?;
441        // If it is a valid slice of length 1 it is a valid `T`.
442        Some(Uninit::decast(part).cast().unwrap())
443    }
444
445    /// Turn this into a slice of standard `MaybeUninit`s.
446    ///
447    /// This is mainly useful for interfacing with other consumers which expect standard library
448    /// types. It may also improve ergonomics for writing to the pointee partially initialized
449    /// instances of `T` that are obtained via other means.
450    ///
451    /// Note that the sequence `from_maybe_uninit_slice`, `into_maybe_uninit_slice` is a no-op. The
452    /// converse is however not the case, as it will potentially discard unused padding present in
453    /// the original `Uninit`.
454    pub fn into_maybe_uninit_slice(self) -> &'a mut [mem::MaybeUninit<T>] {
455        unsafe {
456            // SAFETY: MaybeUninit is a transparent wrapper and need not be initialized.
457            slice::from_raw_parts_mut(
458                self.as_begin_ptr() as *mut mem::MaybeUninit<T>,
459                self.capacity())
460        }
461    }
462}
463
464impl<'a, T: ?Sized> Uninit<'a, T> {
465    /// Create a view to typed uninitialized memory.
466    ///
467    /// It is given a capacity of memory to which it refers in *bytes*.
468    ///
469    /// ## Safety
470    ///
471    /// The `ptr` must describe a valid, *sized* region. Refer to `Layout::for_value_raw` for
472    /// details. This criteria is trivially fulfilled for any sized `T`.
473    ///
474    /// A valid allocation must exist at the pointer with length at least `len`.
475    ///
476    /// In particular, it is **UB** to create this from a reference to a variable of a type for
477    /// which a completely uninitialized content is not valid. The standard type for avoiding the
478    /// UB is `core::mem::MaybeUninit`.
479    ///
480    /// When in doubt, refactor code such that utilization of `from_maybe_uninit` is possible.
481    pub unsafe fn new(ptr: ptr::NonNull<T>, len: usize) -> Self {
482        Uninit {
483            view: UninitView::new(ptr, len),
484            mutable: PhantomData,
485        }
486    }
487
488    /// Return the number of bytes this may view.
489    pub fn byte_capacity(&self) -> usize {
490        self.view.byte_capacity()
491    }
492
493    /// Check if the view fits some layout.
494    ///
495    /// The `cast` to a type of the provided layout will work without error.
496    pub fn fits(&self, layout: Layout) -> bool {
497        self.view.fits(layout)
498    }
499
500    /// View the same uninit as untyped memory.
501    pub fn as_memory(self) -> Uninit<'a, ()> {
502        Uninit::decast(self)
503    }
504
505    /// A private version of the unsafe `from_view`.
506    ///
507    /// This must never be exposed.
508    fn from_presumed_mutable_view(view: UninitView<'a, T>) -> Self {
509        Uninit {
510            view,
511            mutable: PhantomData,
512        }
513    }
514
515    /// Borrow a view of the `Uninit` region.
516    ///
517    /// This is the equivalent of `&*mut_ref as *const _` but never runs afoul of accidentally
518    /// creating an actual reference.
519    pub fn borrow(&self) -> UninitView<'_, T> {
520        self.view
521    }
522
523    /// Borrow the `Uninit` region for a shorter duration.
524    ///
525    /// This is the equivalent of `&mut *mut_ref as *mut _` but never runs afoul of accidentally
526    /// creating an actual reference.
527    pub fn borrow_mut(&mut self) -> Uninit<'_, T> {
528        Uninit::from_presumed_mutable_view(self.view)
529    }
530
531    /// Get the byte size of the total allocation.
532    pub const fn size(&self) -> usize {
533        self.view.size()
534    }
535}
536impl UninitView<'_, ()> {
537    /// Create a uninit view from raw memory.
538    ///
539    /// ## Safety
540    /// A valid allocation must exist at the pointer with length at least `len`.
541    ///
542    /// In particular, it is **UB** to create this from a reference to a variable of a type for
543    /// which a completely uninitialized content is not valid. The standard type for avoiding the
544    /// UB is `core::mem::MaybeUninit`.
545    ///
546    /// When in doubt, refactor code such that utilization of `from_maybe_uninit` is possible.
547    pub unsafe fn from_memory(ptr: ptr::NonNull<u8>, len: usize) -> Self {
548        UninitView {
549            ptr: ptr.cast(),
550            len,
551            lifetime: PhantomData,
552            typed: PhantomData,
553        }
554    }
555
556    /// Split so that the second part fits the layout.
557    ///
558    /// See [`Uninit::split_layout`] for more details.
559    ///
560    /// [`Uninit::split_layout`]: ./struct.Uninit.html#method.split_layout
561    pub fn split_layout(&mut self, layout: Layout) -> Option<Self> {
562        let align = self.ptr.as_ptr()
563            .align_offset(layout.align());
564        let aligned_len = self.len
565            .checked_sub(align)
566            .and_then(|len| len.checked_sub(layout.size()));
567
568        if aligned_len.is_none() {
569            return None;
570        }
571
572        let aligned = self.split_at_byte(align)?;
573        assert!(aligned.fits(layout));
574        Some(aligned)
575    }
576}
577
578impl<'a> UninitView<'a, ()> {
579    fn decast<T: ?Sized>(view: UninitView<'a, T>) -> Self {
580        UninitView {
581            ptr: view.ptr.cast(),
582            len: view.len,
583            lifetime: PhantomData,
584            typed: PhantomData,
585        }
586    }
587
588    /// Split so that the tail is aligned and valid for a `U`.
589    pub fn split_cast<U>(&mut self) -> Option<UninitView<'a, U>> {
590        let split = self.split_layout(Layout::new::<U>())?;
591        let cast = split.cast::<U>().unwrap();
592        Some(cast)
593    }
594
595    /// Split so that the tail is aligned for a slice `[U]`.
596    pub fn split_slice<U>(&mut self) -> Option<UninitView<'a, [U]>> {
597        let layout = Layout::for_value::<[U]>(&[]);
598        let split = self.split_layout(layout)?;
599        let cast = split.cast_slice::<U>().unwrap();
600        Some(cast)
601    }
602}
603
604impl<T> UninitView<'_, T> {
605    /// Invent a new uninit allocation for a zero-sized type (ZST).
606    ///
607    /// # Panics
608    /// This method panics when the type parameter is not a zero sized type.
609    pub fn invent_for_zst() -> Self {
610        assert_eq!(mem::size_of::<T>(), 0, "Invented ZST uninit invoked with non-ZST");
611        let dangling = ptr::NonNull::<T>::dangling();
612        // SAFETY: all bytes are within the allocation.
613        let raw = unsafe { UninitView::from_memory(dangling.cast(), 0) };
614        raw.cast().unwrap()
615    }
616}
617
618impl<'a, T> UninitView<'a, T> {
619    /// Split the uninit view at a byte boundary.
620    ///
621    /// See [`Uninit::split_at_byte`] for more details.
622    ///
623    /// [`Uninit::split_at_byte`]: ./struct.Uninit.html#method.split_at_byte
624    pub fn split_at_byte(&mut self, at: usize) -> Option<UninitView<'a, ()>> {
625        if self.len < at || at < mem::size_of::<T>() {
626            return None;
627        }
628
629        let base = self.ptr.as_ptr();
630        // SAFETY: by `from_memory`, all offsets `< len` are within the allocation.
631        // In particular, no pointer within or one-past-the-end is null.
632        let next_base = unsafe { ptr::NonNull::new_unchecked(base.add(at)) };
633        let next_len = self.len - at;
634        self.len = at;
635
636        // SAFETY: within one allocation, namely the one we are in.
637        let other = unsafe { UninitView::from_memory(next_base.cast(), next_len) };
638        Some(other)
639    }
640
641    /// Create an view to the inner bytes of a `MaybeUninit`.
642    ///
643    /// This is hardly useful on its own but since `UninitView` mirrors the traversal methods of
644    /// `Uninit` it can be used to get pointers to already initialized elements in an immutable
645    /// context.
646    pub fn from_maybe_uninit(mem: &'a mem::MaybeUninit<T>) -> Self {
647        let ptr = ptr::NonNull::new(mem.as_ptr() as *mut T).unwrap();
648        let raw = unsafe {
649            // SAFETY:
650            // * unaliased as we had a mutable reference
651            // * we will not write through the pointer created
652            UninitView::from_memory(ptr.cast(), mem::size_of_val(mem))
653        };
654        raw.cast().unwrap()
655    }
656
657    /// Try to cast to an `UninitView` for a slice type.
658    pub fn cast_slice<U>(self) -> Result<UninitView<'a, [U]>, Self> {
659        let empty = Layout::for_value::<[U]>(&[]);
660
661        if !self.fits(empty) {
662            return Err(self)
663        }
664
665        Ok(UninitView {
666            ptr: {
667                let base = self.ptr.as_ptr() as *mut T;
668                let element = Layout::new::<U>();
669                let slice_len = if element.size() == 0 {
670                    usize::MAX
671                } else {
672                    self.len / element.size()
673                };
674                let slice = ptr::slice_from_raw_parts_mut(base as *mut U, slice_len);
675                ptr::NonNull::new(slice).unwrap()
676            },
677            len: self.len,
678            lifetime: PhantomData,
679            typed: PhantomData,
680        })
681    }
682
683    /// Split off the tail that is not required for holding an instance of `T`.
684    pub fn split_to_fit(&mut self) -> UninitView<'a, ()> {
685        self.split_at_byte(mem::size_of::<T>()).unwrap()
686    }
687
688    /// Turn this into a reference to standard `MaybeUninit`.
689    ///
690    /// This is mainly useful for interfacing with other consumers which expect standard library
691    /// types and to mirror `Uninit`.
692    ///
693    /// Note that the sequence `from_maybe_uninit`, `into_maybe_uninit` is a no-op. The converse is
694    /// however not the case, as it will potentially discard unused padding present in the original
695    /// `Uninit`.
696    pub fn into_maybe_uninit(self) -> &'a mem::MaybeUninit<T> {
697        // SAFETY: MaybeUninit is a transparent wrapper and need not be initialized.
698        unsafe { &*(self.as_ptr() as *const mem::MaybeUninit<T>) }
699    }
700}
701
702impl<'a, T: ?Sized> UninitView<'a, T> {
703    /// Create a reference to typed uninitialized memory.
704    ///
705    /// It is given a capacity of memory to which it refers in *bytes*.
706    ///
707    /// ## Safety
708    ///
709    /// The `ptr` must describe a valid, *sized* region. Refer to `Layout::for_value_raw` for
710    /// details. This criteria is trivially fulfilled for any sized `T`.
711    ///
712    /// A valid allocation must exist at the pointer with length at least `len`.
713    ///
714    /// In particular, it is **UB** to create this from a reference to a variable of a type for
715    /// which a completely uninitialized content is not valid. The standard type for avoiding the
716    /// UB is `core::mem::MaybeUninit`.
717    ///
718    /// When in doubt, refactor code such that utilization of `from_maybe_uninit` is possible.
719    pub unsafe fn new(ptr: ptr::NonNull<T>, len: usize) -> Self {
720        UninitView {
721            ptr,
722            len,
723            lifetime: PhantomData,
724            typed: PhantomData,
725        }
726    }
727
728    /// Return the number of bytes this may refer to.
729    pub fn byte_capacity(&self) -> usize {
730        self.len
731    }
732
733    /// Try to cast to an `UninitView` for another type.
734    pub fn cast<U>(self) -> Result<UninitView<'a, U>, Self> {
735        if !self.fits(Layout::new::<U>()) {
736            return Err(self);
737        }
738
739        Ok(UninitView {
740            ptr: self.ptr.cast(),
741            len: self.len,
742            lifetime: PhantomData,
743            typed: PhantomData,
744        })
745    }
746
747    /// Acquires the underlying `*const T` pointer.
748    pub const fn as_ptr(&self) -> *const T {
749        self.ptr.as_ptr() as *const T
750    }
751
752    /// Acquires the underlying pointer as a `NonNull`.
753    pub fn as_non_null(&self) -> ptr::NonNull<T> {
754        self.ptr
755    }
756
757    /// Dereferences the content.
758    ///
759    /// The resulting lifetime is bound to self so this behaves "as if" it were actually an
760    /// instance of T that is getting borrowed. If a longer lifetime is needed, use `into_ref`.
761    ///
762    /// ## Safety
763    /// The caller must ensure that the content has already been initialized.
764    pub unsafe fn as_ref(&self) -> &T {
765        self.into_ref()
766    }
767
768    /// Turn this into a reference to the content.
769    ///
770    /// ## Safety
771    /// The caller must ensure that the content has already been initialized.
772    pub unsafe fn into_ref(self) -> &'a T {
773        &*self.as_ptr()
774    }
775}
776
777impl<'a, T> UninitView<'a, [T]> {
778    /// Creates a pointer to an empty slice.
779    ///
780    /// Note that it will **not** be a mutable empty slice which means that it would be **UB** to
781    /// use it as an `Uninit`.
782    pub fn empty() -> Self {
783        UninitView {
784            ptr: {
785                let base = ptr::NonNull::<T>::dangling().as_ptr();
786                let slice = ptr::slice_from_raw_parts_mut(base, 0);
787                ptr::NonNull::new(slice).unwrap()
788            },
789            len: 0,
790            lifetime: PhantomData,
791            typed: PhantomData,
792        }
793    }
794
795    /// Create an view on potentially uninitialized memory bytes of a slice of `MaybeUninit`.
796    pub fn from_maybe_uninit_slice(mem: &'a [mem::MaybeUninit<T>]) -> Self {
797        let ptr = ptr::NonNull::from(mem);
798        let raw = unsafe {
799            // SAFETY:
800            // * can write uninitialized bytes as much as we want
801            UninitView::from_memory(ptr.cast(), mem::size_of_val(mem))
802        };
803        raw.cast_slice().unwrap()
804    }
805
806    /// Get the pointer to the first element of the slice.
807    pub fn as_begin_ptr(&self) -> *const T {
808        self.ptr.as_ptr() as *const T
809    }
810
811    /// Calculate the theoretical capacity of a slice in the pointed-to allocation.
812    pub fn capacity(&self) -> usize {
813        self.size()
814            .checked_div(mem::size_of::<T>())
815            .unwrap_or_else(usize::max_value)
816    }
817
818    /// Split the slice at an index.
819    pub fn split_at(&mut self, at: usize) -> Option<Self> {
820        // NOTE: Slice pointers are blocked by Rust stabilization we can not create one from a real
821        // reference to slice as that would restrict us to the memory covered by the reference.
822        // NOTE: Tracked here https://github.com/rust-lang/rust/issues/36925
823        let bytes = match at.checked_mul(mem::size_of::<T>()) {
824            None => return None,
825            Some(byte) if byte > self.len => return None,
826            Some(byte) => byte,
827        };
828
829        let next_len = self.len - bytes;
830        self.len = bytes;
831
832        let base = self.ptr.as_ptr() as *mut u8;
833        // SAFETY: was previously in bounds.
834        let next_base = unsafe { ptr::NonNull::new_unchecked(base.add(bytes)) };
835
836        // SAFETY: total allocation length at least `self.len + next_len`.
837        let other = unsafe { UninitView::from_memory(next_base, next_len) };
838        Some(other.cast_slice().unwrap())
839    }
840
841    /// Get the trailing bytes behind the slice.
842    ///
843    /// The underlying allocation need not be a multiple of the slice element size which may leave
844    /// unusable bytes. This splits these unusable bytes into an untyped `Uninit` which can be
845    /// reused arbitrarily.
846    ///
847    /// This operation is idempotent.
848    pub fn shrink_to_fit(&mut self) -> UninitView<'a, ()> {
849        UninitView::decast(self.split_at(self.capacity()).unwrap())
850    }
851
852    /// Split the first element from the slice.
853    pub fn split_first(&mut self) -> Option<UninitView<'a, T>> {
854        let mut part = self.split_at(1)?;
855        // Now we are the first part, but we wanted the first to be split off.
856        mem::swap(self, &mut part);
857        // If it is a valid slice of length 1 it is a valid `T`.
858        Some(UninitView::decast(part).cast().unwrap())
859    }
860
861    /// Split the last element from the slice.
862    pub fn split_last(&mut self) -> Option<UninitView<'a, T>> {
863        // Explicitely wrap here: If capacity is 0 then `0 < size_of::<T> ` and the split will fail.
864        let split = self.capacity().wrapping_sub(1);
865        let part = self.split_at(split)?;
866        // If it is a valid slice of length 1 it is a valid `T`.
867        Some(UninitView::decast(part).cast().unwrap())
868    }
869
870    /// Turn this into a slice of standard `MaybeUninit`s.
871    ///
872    /// This is mainly useful for interfacing with other consumers which expect standard library
873    /// types and to mirror `Uninit`.
874    ///
875    /// Note that the sequence `from_maybe_uninit_slice`, `into_maybe_uninit_slice` is a no-op. The
876    /// converse is however not the case, as it will potentially discard unused padding present in
877    /// the original `Uninit`.
878    pub fn into_maybe_uninit_slice(self) -> &'a [mem::MaybeUninit<T>] {
879        unsafe {
880            // SAFETY: MaybeUninit is a transparent wrapper and need not be initialized.
881            slice::from_raw_parts(
882                self.as_begin_ptr() as *const mem::MaybeUninit<T>,
883                self.capacity())
884        }
885    }
886}
887
888impl<'a, T: ?Sized> UninitView<'a, T> {
889    /// Check if the view fits some layout.
890    ///
891    /// The `cast` to a type of the provided layout will work without error.
892    pub fn fits(&self, layout: Layout) -> bool {
893        self.ptr.as_ptr().cast::<u8>().align_offset(layout.align()) == 0
894            && layout.size() <= self.len
895    }
896
897    /// Borrow another view of the `Uninit` region.
898    pub fn borrow(&self) -> UninitView<'_, T> {
899        *self
900    }
901
902    /// Get the byte size of the total allocation.
903    pub const fn size(&self) -> usize {
904        self.len
905    }
906}
907
908impl<'a, T> From<&'a mut mem::MaybeUninit<T>> for Uninit<'a, T> {
909    fn from(mem: &'a mut mem::MaybeUninit<T>) -> Self {
910        Uninit::<T>::from_maybe_uninit(mem)
911    }
912}
913
914impl<'a, T> From<&'a mut [mem::MaybeUninit<T>]> for Uninit<'a, [T]> {
915    fn from(mem: &'a mut [mem::MaybeUninit<T>]) -> Self {
916        Uninit::<[T]>::from_maybe_uninit_slice(mem)
917    }
918}
919
920impl<'a, T> From<&'a mem::MaybeUninit<T>> for UninitView<'a, T> {
921    fn from(mem: &'a mem::MaybeUninit<T>) -> Self {
922        UninitView::from_maybe_uninit(mem)
923    }
924}
925
926impl<'a, T> From<&'a [mem::MaybeUninit<T>]> for UninitView<'a, [T]> {
927    fn from(mem: &'a [mem::MaybeUninit<T>]) -> Self {
928        UninitView::<[T]>::from_maybe_uninit_slice(mem)
929    }
930}
931
932impl<T: ?Sized> fmt::Debug for Uninit<'_, T> {
933   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
934       f.debug_tuple("Uninit")
935           .field(&self.view.ptr)
936           .field(&self.view.len)
937           .finish()
938   }
939}
940
941impl<T: ?Sized> fmt::Debug for UninitView<'_, T> {
942   fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
943       f.debug_tuple("UninitView")
944           .field(&self.ptr)
945           .field(&self.len)
946           .finish()
947   }
948}
949
950impl<'a, T> From<Uninit<'a, T>> for UninitView<'a, T> {
951    fn from(uninit: Uninit<'a, T>) -> Self {
952        uninit.view
953    }
954}
955
956impl<T> Default for Uninit<'_, [T]> {
957   fn default() -> Self {
958       Uninit::empty()
959   }
960}
961
962impl<T> Default for UninitView<'_, [T]> {
963   fn default() -> Self {
964       UninitView::empty()
965   }
966}
967
968impl<T: ?Sized> Clone for UninitView<'_, T> {
969    fn clone(&self) -> Self {
970        *self
971    }
972}
973
974impl<T: ?Sized> Copy for UninitView<'_, T> { }
975
976unsafe impl<'a, T, U: ?Sized> CoerciblePtr<U> for UninitView<'a, T> {
977    type Pointee = T;
978    type Output = UninitView<'a, U>;
979    fn as_sized_ptr(&mut self) -> *mut T {
980        self.as_ptr() as *mut T
981    }
982    unsafe fn replace_ptr(self, new: *mut U) -> UninitView<'a, U> {
983        let length = self.byte_capacity();
984        debug_assert_eq!(self.as_ptr() as *const u8, new as *const u8);
985        // SAFETY: caller guarantees this is equal to our pointer, which is non-null
986        let new = ptr::NonNull::new_unchecked(new);
987        UninitView::new(new, length)
988    }
989}
990
991unsafe impl<'a, T, U: ?Sized> CoerciblePtr<U> for Uninit<'a, T> {
992    type Pointee = T;
993    type Output = Uninit<'a, U>;
994
995    fn as_sized_ptr(&mut self) -> *mut T {
996        self.as_ptr()
997    }
998
999    unsafe fn replace_ptr(self, new: *mut U) -> Uninit<'a, U> {
1000        let length = self.byte_capacity();
1001        debug_assert_eq!(self.as_ptr() as *const u8, new as *const u8);
1002        // SAFETY: caller guarantees this is equal to our pointer, which is non-null
1003        let new = ptr::NonNull::new_unchecked(new);
1004        Uninit::new(new, length)
1005    }
1006}
1007
1008#[cfg(test)]
1009mod tests {
1010    use super::Uninit;
1011
1012    #[test]
1013    fn lifetime_longer() {
1014        fn _long<'a, T>(_: Uninit<'a, &'static T>) { }
1015    }
1016
1017    #[test]
1018    fn lifetime_shorter() {
1019        fn _short<'a, T>(_: Uninit<'static, &'a T>) { }
1020    }
1021
1022    #[test]
1023    fn in_a_struct() {
1024        enum _List<T> {
1025            Nil,
1026            Cons(T, Uninit<'static, T>),
1027        }
1028    }
1029}