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);
}