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}