array_insertion/
lib.rs

1//! Insert an element into the array.
2//!
3//! # Examples
4//! ```
5//! use std::mem::MaybeUninit;
6//!
7//! use array_insertion::array_insert;
8//!
9//! fn uninit_array<T, const N: usize>() -> [MaybeUninit<T>; N] {
10//!     unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
11//! }
12//!
13//! let mut array = uninit_array::<String, 10>();
14//! array[0].write("A".to_owned());
15//! array[1].write("B".to_owned());
16//! array[2].write("C".to_owned());
17//! array[3].write("E".to_owned());
18//! array[4].write("F".to_owned());
19//!
20//! unsafe {
21//!     array_insert(&mut array, 3, 5, "D".to_owned());
22//!
23//!     let init = &*(&array[..6] as *const [_] as *const [String]);
24//!     assert_eq!(init, ["A", "B", "C", "D", "E", "F"]);
25//!
26//!     for e in &mut array[..6] {
27//!         e.assume_init_drop();
28//!     }
29//! }
30//! ```
31//!
32//! ```
33//! use std::mem::MaybeUninit;
34//!
35//! use array_insertion::array_splice;
36//!
37//! fn uninit_array<T, const N: usize>() -> [MaybeUninit<T>; N] {
38//!     unsafe { MaybeUninit::<[MaybeUninit<T>; N]>::uninit().assume_init() }
39//! }
40//!
41//! let mut dst = uninit_array::<String, 10>();
42//! dst[0].write("A".to_owned());
43//! dst[1].write("B".to_owned());
44//! dst[2].write("C".to_owned());
45//! dst[3].write("F".to_owned());
46//! dst[4].write("G".to_owned());
47//! let mut src = uninit_array::<String, 10>();
48//! src[0].write("D".to_owned());
49//! src[1].write("E".to_owned());
50//!
51//! unsafe {
52//!     array_splice(&mut dst, 3, 5, &src, 2);
53//!
54//!     let init = &*(&dst[..7] as *const [_] as *const [String]);
55//!     assert_eq!(init, ["A", "B", "C", "D", "E", "F", "G"]);
56//!
57//!     for e in &mut dst[..7] {
58//!         e.assume_init_drop();
59//!     }
60//! }
61//! ```
62
63use std::{mem::MaybeUninit, ptr};
64
65/// Insert an element into the array.
66///
67/// # Safety
68/// - `array[..len]` is initialized,
69/// - `array[len..]` is uninitialized,
70/// - `len < N`, and
71/// - `i <= len`.
72pub unsafe fn array_insert<T, const N: usize>(
73    array: &mut [MaybeUninit<T>; N],
74    i: usize,
75    len: usize,
76    elt: T,
77) {
78    debug_assert!(i <= len && len < N);
79    let count = len - i;
80    let dst = array[i + 1..][..count].as_mut_ptr();
81    // `src` should be after `dst` for Stacked Borrows.
82    let src = array[i..][..count].as_ptr();
83    ptr::copy(src, dst, count);
84    array[i].write(elt);
85}
86
87/// Insert elements into the array from the other array.
88///
89/// # Safety
90/// - `dst[..dst_len]` is initialized,
91/// - `dst[dst_len..]` is uninitialized,
92/// - `src[..src_len]` is initialized,
93/// - `dst_len + src_len <= N`, and
94/// - `i <= dst_len`.
95pub unsafe fn array_splice<T, const N: usize>(
96    dst: &mut [MaybeUninit<T>; N],
97    i: usize,
98    dst_len: usize,
99    src: &[MaybeUninit<T>; N],
100    src_len: usize,
101) {
102    debug_assert!(i <= dst_len && dst_len + src_len <= N);
103    let count = dst_len - i;
104    let dst_ptr = dst[i + src_len..][..count].as_mut_ptr();
105    let src_ptr = dst[i..][..count].as_ptr();
106    ptr::copy(src_ptr, dst_ptr, count);
107    let count = src_len;
108    let src_ptr = src[..count].as_ptr();
109    let dst_ptr = dst[i..][..count].as_mut_ptr();
110    ptr::copy_nonoverlapping(src_ptr, dst_ptr, count);
111}