#![no_std]
use core::marker::PhantomData;
pub unsafe trait RecursiveArray<T>: Sized + AsRef<[T]> + AsMut<[T]> {
const LENGTH: usize;
const EMPTY: EmptyRecursiveArray = EmptyRecursiveArray;
fn empty() -> EmptyRecursiveArray {
EmptyRecursiveArray
}
fn len(&self) -> usize {
Self::LENGTH
}
fn from_array<const N: usize>(array: [T; N]) -> Self {
if N != Self::LENGTH {
panic!(
"tried to convert an array of length {} to a recursive array of length {}",
N,
Self::LENGTH,
);
}
unsafe { runtime_checked_transmute(array) }
}
fn to_array<const N: usize>(self) -> [T; N] {
if N != Self::LENGTH {
panic!(
"tried to convert a recursive array of length {} to an array of length {}",
Self::LENGTH,
N,
);
}
unsafe { runtime_checked_transmute(self) }
}
fn from_slice(slice: &[T]) -> &Self {
if slice.len() != Self::LENGTH {
panic!(
"tried to convert a slice of length {} to a recursive array of length {}",
slice.len(),
Self::LENGTH,
);
}
unsafe { &*slice.as_ptr().cast() }
}
fn from_mut_slice(slice: &mut [T]) -> &mut Self {
if slice.len() != Self::LENGTH {
panic!(
"tried to convert a slice of length {} to a recursive array of length {}",
slice.len(),
Self::LENGTH,
);
}
unsafe { &mut *slice.as_mut_ptr().cast() }
}
fn as_slice(&self) -> &[T] {
unsafe { core::slice::from_raw_parts(self as *const Self as *const T, Self::LENGTH) }
}
fn as_mut_slice(&mut self) -> &mut [T] {
unsafe { core::slice::from_raw_parts_mut(self as *mut Self as *mut T, Self::LENGTH) }
}
fn push_back(
self,
item: T,
) -> RecursiveArrayConcatenation<T, Self, RecursiveArraySingleItem<T>> {
RecursiveArrayConcatenation::new(self, RecursiveArraySingleItem::new(item))
}
fn append_back<R: RecursiveArray<T>>(
self,
array: R,
) -> RecursiveArrayConcatenation<T, Self, R> {
RecursiveArrayConcatenation::new(self, array)
}
fn push_front(
self,
item: T,
) -> RecursiveArrayConcatenation<T, RecursiveArraySingleItem<T>, Self> {
RecursiveArrayConcatenation::new(RecursiveArraySingleItem::new(item), self)
}
fn append_front<R: RecursiveArray<T>>(
self,
array: R,
) -> RecursiveArrayConcatenation<T, R, Self> {
RecursiveArrayConcatenation::new(array, self)
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, Default)]
pub struct EmptyRecursiveArray;
impl<T> AsRef<[T]> for EmptyRecursiveArray {
fn as_ref(&self) -> &[T] {
&[]
}
}
impl<T> AsMut<[T]> for EmptyRecursiveArray {
fn as_mut(&mut self) -> &mut [T] {
&mut []
}
}
unsafe impl<T> RecursiveArray<T> for EmptyRecursiveArray {
const LENGTH: usize = 0;
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Default)]
#[repr(transparent)]
pub struct RecursiveArraySingleItem<T> {
item: T,
}
impl<T> AsRef<[T]> for RecursiveArraySingleItem<T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T> AsMut<[T]> for RecursiveArraySingleItem<T> {
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
unsafe impl<T> RecursiveArray<T> for RecursiveArraySingleItem<T> {
const LENGTH: usize = 1;
}
impl<T> RecursiveArraySingleItem<T> {
pub fn new(item: T) -> Self {
Self { item }
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq, Default)]
#[repr(C)]
pub struct RecursiveArrayConcatenation<T, A: RecursiveArray<T>, B: RecursiveArray<T>> {
a: A,
b: B,
phantom: PhantomData<T>,
}
impl<T, A: RecursiveArray<T>, B: RecursiveArray<T>> AsRef<[T]>
for RecursiveArrayConcatenation<T, A, B>
{
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<T, A: RecursiveArray<T>, B: RecursiveArray<T>> AsMut<[T]>
for RecursiveArrayConcatenation<T, A, B>
{
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
unsafe impl<T, A: RecursiveArray<T>, B: RecursiveArray<T>> RecursiveArray<T>
for RecursiveArrayConcatenation<T, A, B>
{
const LENGTH: usize = A::LENGTH + B::LENGTH;
}
impl<T, A: RecursiveArray<T>, B: RecursiveArray<T>> RecursiveArrayConcatenation<T, A, B> {
pub fn new(a: A, b: B) -> Self {
Self {
a,
b,
phantom: PhantomData,
}
}
}
impl<T, A: RecursiveArray<T>> RecursiveArrayConcatenation<T, A, RecursiveArraySingleItem<T>> {
pub fn pop_back(self) -> (T, A) {
(self.b.item, self.a)
}
}
impl<T, B: RecursiveArray<T>> RecursiveArrayConcatenation<T, RecursiveArraySingleItem<T>, B> {
pub fn pop_front(self) -> (T, B) {
(self.a.item, self.b)
}
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub struct RecursiveArrayArrayWrapper<const N: usize, T> {
array: [T; N],
}
impl<const N: usize, T> RecursiveArrayArrayWrapper<N, T> {
pub fn new(array: [T; N]) -> Self {
Self { array }
}
}
impl<const N: usize, T> AsRef<[T]> for RecursiveArrayArrayWrapper<N, T> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<const N: usize, T> AsMut<[T]> for RecursiveArrayArrayWrapper<N, T> {
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
unsafe impl<const N: usize, T> RecursiveArray<T> for RecursiveArrayArrayWrapper<N, T> {
const LENGTH: usize = N;
}
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
#[repr(transparent)]
pub struct RecursiveArrayMultiplier<const N: usize, T, A: RecursiveArray<T>> {
multiplied: [A; N],
phantom: PhantomData<T>,
}
impl<const N: usize, T, A: RecursiveArray<T>> RecursiveArrayMultiplier<N, T, A> {
pub fn new(values: [A; N]) -> Self {
Self {
multiplied: values,
phantom: PhantomData,
}
}
}
impl<const N: usize, T, A: RecursiveArray<T>> AsRef<[T]> for RecursiveArrayMultiplier<N, T, A> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl<const N: usize, T, A: RecursiveArray<T>> AsMut<[T]> for RecursiveArrayMultiplier<N, T, A> {
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
unsafe impl<const N: usize, T, A: RecursiveArray<T>> RecursiveArray<T>
for RecursiveArrayMultiplier<N, T, A>
{
const LENGTH: usize = A::LENGTH * N;
}
#[macro_export]
macro_rules! recursive_array {
[] => {
::recursive_array::EmptyRecursiveArray
};
[$item: expr $(,)?] => {
::recursive_array::RecursiveArraySingleItem::new($item)
};
[$first_item: expr, $($item: expr),+] => {
::recursive_array::RecursiveArrayConcatenation::new(
::recursive_array::RecursiveArraySingleItem::new($first_item),
::recursive_array::recursive_array![$($item),+],
)
};
}
#[macro_export]
macro_rules! recursive_array_type_of_size {
($item_type: ty, $size: expr) => {
::recursive_array::RecursiveArrayArrayWrapper<{$size}, $item_type>
};
}
unsafe fn runtime_checked_transmute<A, B>(a: A) -> B {
if core::mem::size_of::<A>() != core::mem::size_of::<B>() {
panic!(
"tried to transmute a type of size {} to a type of size {}",
core::mem::size_of::<A>(),
core::mem::size_of::<B>()
);
}
#[repr(C)]
union Union<A, B> {
a: core::mem::ManuallyDrop<A>,
b: core::mem::ManuallyDrop<B>,
}
let a = core::mem::ManuallyDrop::new(a);
core::mem::ManuallyDrop::into_inner(Union { a }.b)
}