1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
use ::core::{mem::ManuallyDrop, ptr};
use ::mischief::{In, Region, Slot};
use ::ptr_meta::Pointee;
use ::situ::DropRaw;

use crate::{Emplace, EmplaceExt};

macro_rules! impl_builtin {
    ($($ty:ty),*) => {
        $(
            // SAFETY:
            // - `emplaced_meta` returns `()`, the only valid metadata for
            //  `Sized` types.
            // - `emplace_unsized_unchecked` initializes its `out` parameter by
            //   writing to it.
            unsafe impl<R: Region> Emplace<$ty, R> for $ty {
                fn emplaced_meta(&self) -> <Self as Pointee>::Metadata {}

                unsafe fn emplace_unsized_unchecked(
                    self,
                    out: In<Slot<'_, $ty>, R>,
                ) {
                    In::into_inner(out).write(self);
                }
            }
        )*
    }
}

impl_builtin!(i8, u8, bool, ());

// SAFETY:
// - `emplaced_meta` returns `()`, the only valid metadata for `Sized` types.
// - `emplace_unsized_unchecked` emplaces to every element of the `out` slot,
//   which initializes it.
unsafe impl<E, T, R: Region, const N: usize> Emplace<[T; N], R> for [E; N]
where
    E: Emplace<T, R>,
    T: DropRaw,
{
    fn emplaced_meta(&self) -> <Self as Pointee>::Metadata {}

    unsafe fn emplace_unsized_unchecked(self, out: In<Slot<'_, [T; N]>, R>) {
        let emplacers = ManuallyDrop::new(self);
        let mut out = In::into_inner(out);
        for i in 0..N {
            // SAFETY: `i` is in bounds because it must be less than the length
            // of the array, `N`.
            let out_i = unsafe { out.as_mut().get_unchecked(i) };
            // SAFETY: `out_i` is located in `R` because `out` is located in `R`
            // and `out_i` is an element of `out`.
            let out_i = unsafe { In::new_unchecked(out_i) };
            // SAFETY: The pointer being read is from a reference, so it must be
            // valid for reads, properly aligned, and point to an initialized
            // value.
            let emplacer_i = unsafe { ptr::read(&emplacers[i]) };
            emplacer_i.emplace(out_i);
        }
    }
}