range-mutex 0.1.7

A `Mutex<[T]>`-like type, that allows locking different ranges separately.
Documentation
mod range;
use std::{cell::UnsafeCell, mem::ManuallyDrop, ops::Range, ptr::NonNull};

pub use range::range;

pub fn transpose_unsafecell_slice<T>(
    slice: &[UnsafeCell<T>],
) -> &UnsafeCell<[T]> {
    // SAFETY: [UnsafeCell<T>] has the same in-memory representation as
    // UnsafeCell<[T]>.
    unsafe { &*(slice as *const [UnsafeCell<T>] as *const UnsafeCell<[T]>) }
}

/// Assumes r1 and r2 are nonempty.
pub fn overlaps(r1: &Range<usize>, r2: &Range<usize>) -> bool {
    r1.end > r2.start && r1.start < r2.end
}

pub fn wrap_unsafecell_array<T, const N: usize>(
    array: [T; N],
) -> [UnsafeCell<T>; N] {
    // SAFETY: An owned [T; N] can be interpreted as [UnsafeCell<T>; N],
    // since UnsafeCell<T> has the same in-memory representation as T,
    // and the ownership ensures that "adding" interior mutability is not an
    // issue.
    unsafe {
        let array = ManuallyDrop::new(array);
        std::mem::transmute_copy(&array)
    }
}

pub fn unwrap_unsafecell_array<T, const N: usize>(
    array: [UnsafeCell<T>; N],
) -> [T; N] {
    // SAFETY: An owned [UnsafeCell<T>; N] can be interpreted as [T;
    // N], since UnsafeCell<T> has the same in-memory representation as T,
    // and the ownership ensures that "removing" interior mutability is not an
    // issue.
    unsafe {
        let array = ManuallyDrop::new(array);
        std::mem::transmute_copy(&array)
    }
}

pub fn wrap_unsafecell_slice<T>(
    slice: &mut [T],
) -> &mut [UnsafeCell<T>] {
    // SAFETY: A uniquely borrowed [T] can be interpreted as [UnsafeCell<T>],
    // since UnsafeCell<T> has the same in-memory representation as T,
    // and the unique borrow ensures that "adding" interior mutability is not an
    // issue.
    unsafe { &mut *(slice as *mut [T] as *mut [UnsafeCell<T>]) }
}

pub fn unwrap_unsafecell_slice<T>(
    slice: &mut [UnsafeCell<T>],
) -> &mut [T] {
    // SAFETY: A uniquely borrowed [UnsafeCell<T>] can be interpreted as [T],
    // since UnsafeCell<T> has the same in-memory representation as T,
    // and the unique borrow ensures that "removing" interior mutability is not
    // an issue.
    unsafe { &mut *(slice as *mut [UnsafeCell<T>] as *mut [T]) }
}

pub fn wrap_unsafecell_vec<T>(vec: Vec<T>) -> Vec<UnsafeCell<T>> {
    // SAFETY: Owned `T`s can be interpreted as `UnsafeCell<T>`s,
    // since UnsafeCell<T> has the same in-memory representation as T,
    // and the ownership ensures that "adding" interior mutability is not an
    // issue.
    let mut vec = ManuallyDrop::new(vec);
    let length = vec.len();
    let capacity = vec.capacity();
    let ptr = vec.as_mut_ptr();
    unsafe { Vec::from_raw_parts(ptr.cast(), length, capacity) }
}

pub fn unwrap_unsafecell_vec<T>(vec: Vec<UnsafeCell<T>>) -> Vec<T> {
    // SAFETY: Owned `UnsafeCell<T>`s can be interpreted as `T`s,
    // since UnsafeCell<T> has the same in-memory representation as T,
    // and the ownership ensures that "removing" interior mutability is not an
    // issue.
    let mut vec = ManuallyDrop::new(vec);
    let length = vec.len();
    let capacity = vec.capacity();
    let ptr = vec.as_mut_ptr();
    unsafe { Vec::from_raw_parts(ptr.cast(), length, capacity) }
}

/// # Safety:
///
/// See [`pointer::add`].
///
/// More precisely, `slice.as_ptr().add(mid)` must not be UB.
pub unsafe fn split_slice_at<T>(
    slice: NonNull<[T]>,
    mid: usize,
) -> (NonNull<[T]>, NonNull<[T]>) {
    debug_assert!(mid <= slice.len());
    let head_ptr = slice.as_ptr() as *mut T;
    let head_len = mid;
    // SAFETY: discharged to caller
    let tail_ptr = unsafe { head_ptr.add(mid) };
    let tail_len = slice.len() - mid;
    (
        NonNull::new(std::ptr::slice_from_raw_parts_mut(head_ptr, head_len))
            .unwrap(),
        NonNull::new(std::ptr::slice_from_raw_parts_mut(tail_ptr, tail_len))
            .unwrap(),
    )
}