array_removal/
lib.rs

1//! Remove an element from the array.
2//!
3//! # Examples
4//! ```
5//! use std::mem::MaybeUninit;
6//!
7//! use array_removal::array_remove;
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("X".to_owned());
18//! array[4].write("D".to_owned());
19//! array[5].write("E".to_owned());
20//!
21//! unsafe {
22//!     let elt = array_remove(&mut array, 3, 6);
23//!     assert_eq!(elt, "X");
24//!
25//!     let init = &*(&array[..5] as *const [_] as *const [String]);
26//!     assert_eq!(init, ["A", "B", "C", "D", "E"]);
27//!
28//!     for e in &mut array[..5] {
29//!         e.assume_init_drop();
30//!     }
31//! }
32//! ```
33
34use std::{mem::MaybeUninit, ptr};
35
36/// Remove an element from the array.
37///
38/// # Safety
39/// - `array[..len]` is initialized,
40/// - `len <= N`, and
41/// - `i < len`.
42pub unsafe fn array_remove<T, const N: usize>(
43    array: &mut [MaybeUninit<T>; N],
44    i: usize,
45    len: usize,
46) -> T {
47    debug_assert!(i < len && len <= N);
48    let elt = array[i].assume_init_read();
49    let count = len - i - 1;
50    let dst = array[i..][..count].as_mut_ptr();
51    let src = array[i + 1..][..count].as_ptr();
52    ptr::copy(src, dst, count);
53    elt
54}