#![no_std]
#![allow(incomplete_features)]
#![feature(generic_const_exprs)]
pub trait SplitArray<const LEN: usize> {
type Output<const OUT_SIZE: usize>: SplitArray<OUT_SIZE>;
fn split_arr<const LEFT: usize>(&self) -> (&Self::Output<LEFT>, &Self::Output<{ LEN - LEFT }>)
where
[(); LEN - LEFT]:;
fn split_arr_mut<const LEFT: usize>(
&mut self,
) -> (&mut Self::Output<LEFT>, &mut Self::Output<{ LEN - LEFT }>)
where
[(); LEN - LEFT]:;
}
pub trait SplitArrayRaw<const LEN: usize> {
type Output<const OUT_SIZE: usize>: SplitArrayRaw<OUT_SIZE>;
unsafe fn split_arr_raw<const LEFT: usize>(
self,
) -> (Self::Output<LEFT>, Self::Output<{ LEN - LEFT }>)
where
[(); LEN - LEFT]:;
}
pub trait SplitArrayRawMut<const LEN: usize> {
type Output<const OUT_SIZE: usize>: SplitArrayRawMut<OUT_SIZE>;
unsafe fn split_arr_raw_mut<const LEFT: usize>(
self,
) -> (Self::Output<LEFT>, Self::Output<{ LEN - LEFT }>)
where
[(); LEN - LEFT]:;
}
impl<T, const LEN: usize> SplitArray<LEN> for [T; LEN] {
type Output<const OUT_SIZE: usize> = [T; OUT_SIZE];
#[inline]
fn split_arr<const LEFT: usize>(&self) -> (&[T; LEFT], &[T; LEN - LEFT])
where
[(); LEN - LEFT]:,
{
split_arr(self)
}
#[inline]
fn split_arr_mut<const LEFT: usize>(&mut self) -> (&mut [T; LEFT], &mut [T; LEN - LEFT])
where
[(); LEN - LEFT]:,
{
split_arr_mut(self)
}
}
impl<T, const LEN: usize> SplitArrayRaw<LEN> for *const [T; LEN] {
type Output<const OUT_SIZE: usize> = *const [T; OUT_SIZE];
unsafe fn split_arr_raw<const LEFT: usize>(self) -> (*const [T; LEFT], *const [T; LEN - LEFT])
where
[(); LEN - LEFT]:,
{
unsafe { split_arr_raw(self) }
}
}
impl<T, const LEN: usize> SplitArrayRawMut<LEN> for *mut [T; LEN] {
type Output<const OUT_SIZE: usize> = *mut [T; OUT_SIZE];
unsafe fn split_arr_raw_mut<const LEFT: usize>(self) -> (*mut [T; LEFT], *mut [T; LEN - LEFT])
where
[(); LEN - LEFT]:,
{
unsafe { split_arr_raw_mut(self) }
}
}
#[inline]
pub const fn split_arr<const LEFT: usize, const N: usize, T>(
arr: &[T; N],
) -> (&[T; LEFT], &[T; N - LEFT])
where
[(); N - LEFT]:,
{
unsafe {
let (left, right) = split_arr_raw(arr);
(&*left, &*right)
}
}
#[inline]
pub fn split_arr_mut<const LEFT: usize, const N: usize, T>(
arr: &mut [T; N],
) -> (&mut [T; LEFT], &mut [T; N - LEFT])
where
[(); N - LEFT]:,
{
unsafe {
let (left, right) = split_arr_raw_mut(arr);
(&mut *left, &mut *right)
}
}
#[inline]
pub const unsafe fn split_arr_raw<const LEFT: usize, const N: usize, T>(
arr: *const [T; N],
) -> (*const [T; LEFT], *const [T; N - LEFT])
where
[(); N - LEFT]:,
{
let left = arr.cast::<T>();
let right = unsafe { left.add(LEFT) };
(left.cast(), right.cast())
}
#[inline]
pub const unsafe fn split_arr_raw_mut<const LEFT: usize, const N: usize, T>(
arr: *mut [T; N],
) -> (*mut [T; LEFT], *mut [T; N - LEFT])
where
[(); N - LEFT]:,
{
let left = arr as *mut T;
let right = unsafe { left.add(LEFT) };
(left.cast(), right.cast())
}
#[cfg(test)]
mod tests {
use super::*;
use core::ptr::{addr_of, addr_of_mut};
#[test]
fn split_arr() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr::<5>();
assert_eq!(&[0, 1, 2, 3, 4], left);
assert_eq!(&[5, 6, 7], right);
}
#[test]
fn split_arr_infer_size() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr();
assert_eq!(&[0, 1, 2, 3, 4], left);
assert_eq!(&[5, 6, 7], right);
}
#[test]
fn split_arr_left_zero() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr::<0>();
assert_eq!(&[0; 0], left);
assert_eq!(&[0, 1, 2, 3, 4, 5, 6, 7], right);
}
#[test]
fn split_arr_right_zero() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr::<8>();
assert_eq!(&[0, 1, 2, 3, 4, 5, 6, 7], left);
assert_eq!(&[0; 0], right);
}
#[test]
fn split_arr_mut() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr_mut::<5>();
left.clone_from(&[10, 11, 12, 13, 14]);
right.clone_from(&[25, 26, 27]);
assert_eq!(&[10, 11, 12, 13, 14], left);
assert_eq!(&[25, 26, 27], right);
assert_eq!([10, 11, 12, 13, 14, 25, 26, 27], arr);
}
#[test]
fn split_arr_mut_infer_size() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr_mut();
left.clone_from(&[10, 11, 12, 13, 14]);
right.clone_from(&[25, 26, 27]);
assert_eq!(&[10, 11, 12, 13, 14], left);
assert_eq!(&[25, 26, 27], right);
assert_eq!([10, 11, 12, 13, 14, 25, 26, 27], arr);
}
#[test]
fn split_arr_mut_left_zero() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr_mut::<0>();
left.clone_from(&[]);
right.clone_from(&[20, 21, 22, 23, 24, 25, 26, 27]);
assert_eq!(&[0; 0], left);
assert_eq!(&[20, 21, 22, 23, 24, 25, 26, 27], right);
assert_eq!([20, 21, 22, 23, 24, 25, 26, 27], arr);
}
#[test]
fn split_arr_mut_right_zero() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (left, right) = arr.split_arr_mut::<8>();
left.clone_from(&[10, 11, 12, 13, 14, 15, 16, 17]);
right.clone_from(&[]);
assert_eq!(&[10, 11, 12, 13, 14, 15, 16, 17], left);
assert_eq!(&[0; 0], right);
assert_eq!([10, 11, 12, 13, 14, 15, 16, 17], arr);
}
#[test]
fn split_arr_raw() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of!(arr).split_arr_raw::<5>();
assert_eq!([0, 1, 2, 3, 4], *left);
assert_eq!([5, 6, 7], *right);
}
}
#[test]
fn split_arr_raw_infer_size() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of!(arr).split_arr_raw();
assert_eq!([0, 1, 2, 3, 4], *left);
assert_eq!([5, 6, 7], *right);
}
}
#[test]
fn split_arr_raw_left_zero() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of!(arr).split_arr_raw::<0>();
assert_eq!([0; 0], *left);
assert_eq!([0, 1, 2, 3, 4, 5, 6, 7], *right);
}
}
#[test]
fn split_arr_raw_right_zero() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of!(arr).split_arr_raw::<8>();
assert_eq!([0, 1, 2, 3, 4, 5, 6, 7], *left);
assert_eq!([0; 0], *right);
}
}
#[test]
fn split_arr_raw_mut() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of_mut!(arr).split_arr_raw_mut::<5>();
*left = [10, 11, 12, 13, 14];
*right = [25, 26, 27];
assert_eq!([10, 11, 12, 13, 14], *left);
assert_eq!([25, 26, 27], *right);
}
assert_eq!([10, 11, 12, 13, 14, 25, 26, 27], arr);
}
#[test]
fn split_arr_raw_mut_infer_size() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of_mut!(arr).split_arr_raw_mut();
*left = [10, 11, 12, 13, 14];
*right = [25, 26, 27];
assert_eq!([10, 11, 12, 13, 14], *left);
assert_eq!([25, 26, 27], *right);
}
assert_eq!([10, 11, 12, 13, 14, 25, 26, 27], arr);
}
#[test]
fn split_arr_raw_mut_left_zero() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of_mut!(arr).split_arr_raw_mut::<0>();
*left = [];
*right = [20, 21, 22, 23, 24, 25, 26, 27];
assert_eq!([0; 0], *left);
assert_eq!([20, 21, 22, 23, 24, 25, 26, 27], *right);
}
assert_eq!([20, 21, 22, 23, 24, 25, 26, 27], arr);
}
#[test]
fn split_arr_raw_mut_right_zero() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
let (left, right) = addr_of_mut!(arr).split_arr_raw_mut::<8>();
*left = [10, 11, 12, 13, 14, 15, 16, 17];
*right = [];
assert_eq!([10, 11, 12, 13, 14, 15, 16, 17], *left);
assert_eq!([0; 0], *right);
}
assert_eq!([10, 11, 12, 13, 14, 15, 16, 17], arr);
}
#[test]
fn array_impl_defers() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
assert_eq!(crate::split_arr(&arr), arr.split_arr::<5>());
}
#[test]
fn array_impl_defers_mut() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
let (crate_level_left, crate_level_right) = crate::split_arr_mut(&mut arr);
let crate_level_result = (crate_level_left as *mut _, crate_level_right as *mut _);
let (trait_left, trait_right) = arr.split_arr_mut::<5>();
let trait_result = (trait_left as *mut _, trait_right as *mut _);
assert_eq!(crate_level_result, trait_result);
}
#[test]
fn array_impl_defers_raw() {
let arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
assert_eq!(
crate::split_arr_raw(addr_of!(arr)),
addr_of!(arr).split_arr_raw::<5>()
);
}
}
#[test]
fn array_impl_defers_raw_mut() {
let mut arr: [usize; 8] = [0, 1, 2, 3, 4, 5, 6, 7];
unsafe {
assert_eq!(
crate::split_arr_raw_mut(addr_of_mut!(arr)),
addr_of_mut!(arr).split_arr_raw_mut::<5>()
);
}
}
}