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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
//! Insert an element into the array.
//!
//! # Examples
//! ```
//! use std::mem::MaybeUninit;
//!
//! use array_insertion::array_insert;
//!
//! fn uninit_array<T, const N: usize>() -> [MaybeUninit<T>; N] {
//!     unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
//! }
//!
//! let mut array = uninit_array::<String, 10>();
//! array[0].write("A".to_owned());
//! array[1].write("B".to_owned());
//! array[2].write("C".to_owned());
//! array[3].write("E".to_owned());
//! array[4].write("F".to_owned());
//!
//! unsafe {
//!     array_insert(&mut array, 3, 5, "D".to_owned());
//!
//!     let init = &*(&array[..6] as *const [_] as *const [String]);
//!     assert_eq!(init, ["A", "B", "C", "D", "E", "F"]);
//!
//!     for e in &mut array[..6] {
//!         e.assume_init_drop();
//!     }
//! }
//! ```
//!
//! ```
//! use std::mem::MaybeUninit;
//!
//! use array_insertion::array_splice;
//!
//! fn uninit_array<T, const N: usize>() -> [MaybeUninit<T>; N] {
//!     unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
//! }
//!
//! let mut dst = uninit_array::<String, 10>();
//! dst[0].write("A".to_owned());
//! dst[1].write("B".to_owned());
//! dst[2].write("C".to_owned());
//! dst[3].write("F".to_owned());
//! dst[4].write("G".to_owned());
//! let mut src = uninit_array::<String, 10>();
//! src[0].write("D".to_owned());
//! src[1].write("E".to_owned());
//!
//! unsafe {
//!     array_splice(&mut dst, 3, 5, &src, 2);
//!
//!     let init = &*(&dst[..7] as *const [_] as *const [String]);
//!     assert_eq!(init, ["A", "B", "C", "D", "E", "F", "G"]);
//!
//!     for e in &mut dst[..7] {
//!         e.assume_init_drop();
//!     }
//! }
//! ```

use std::{mem::MaybeUninit, ptr};

/// Insert an element into the array.
///
/// # Safety
/// - `array[..len]` is initialized,
/// - `array[len..]` is uninitialized,
/// - `len < N`, and
/// - `i <= len`.
pub unsafe fn array_insert<T, const N: usize>(
    array: &mut [MaybeUninit<T>; N],
    i: usize,
    len: usize,
    elt: T,
) {
    debug_assert!(i <= len && len < N);
    let count = len - i;
    let dst = array[i + 1..][..count].as_mut_ptr();
    // `src` should be after `dst` for Stacked Borrows.
    let src = array[i..][..count].as_ptr();
    ptr::copy(src, dst, count);
    array[i].write(elt);
}

/// Insert elements into the array from the other array.
///
/// # Safety
/// - `dst[..dst_len]` is initialized,
/// - `dst[dst_len..]` is uninitialized,
/// - `src[..src_len]` is initialized,
/// - `dst_len + src_len <= N`, and
/// - `i <= dst_len`.
pub unsafe fn array_splice<T, const N: usize>(
    dst: &mut [MaybeUninit<T>; N],
    i: usize,
    dst_len: usize,
    src: &[MaybeUninit<T>; N],
    src_len: usize,
) {
    debug_assert!(i <= dst_len && dst_len + src_len <= N);
    let count = dst_len - i;
    let dst_ptr = dst[i + src_len..][..count].as_mut_ptr();
    let src_ptr = dst[i..][..count].as_ptr();
    ptr::copy(src_ptr, dst_ptr, count);
    let count = src_len;
    let src_ptr = src[..count].as_ptr();
    let dst_ptr = dst[i..][..count].as_mut_ptr();
    ptr::copy_nonoverlapping(src_ptr, dst_ptr, count);
}