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
//! Remove an element from the array.
//!
//! # Examples
//! ```
//! use std::mem::MaybeUninit;
//!
//! use array_removal::array_remove;
//!
//! 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("X".to_owned());
//! array[4].write("D".to_owned());
//! array[5].write("E".to_owned());
//!
//! unsafe {
//!     let elt = array_remove(&mut array, 3, 6);
//!     assert_eq!(elt, "X");
//!
//!     let init = &*(&array[..5] as *const [_] as *const [String]);
//!     assert_eq!(init, ["A", "B", "C", "D", "E"]);
//!
//!     for e in &mut array[..5] {
//!         e.assume_init_drop();
//!     }
//! }
//! ```

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

/// Remove an element from the array.
///
/// # Safety
/// - `array[..len]` is initialized,
/// - `len <= N`, and
/// - `i < len`.
pub unsafe fn array_remove<T, const N: usize>(
    array: &mut [MaybeUninit<T>; N],
    i: usize,
    len: usize,
) -> T {
    debug_assert!(i < len && len <= N);
    let elt = array[i].assume_init_read();
    let count = len - i - 1;
    let dst = array[i..][..count].as_mut_ptr();
    let src = array[i + 1..][..count].as_ptr();
    ptr::copy(src, dst, count);
    elt
}