#![no_std]
extern crate alloc;
use core::{ptr::{NonNull, self}, alloc::Layout, mem::MaybeUninit, ops::{Index, IndexMut, Deref}, borrow::{Borrow, BorrowMut}};
use alloc::{boxed::Box, alloc::{alloc, handle_alloc_error}};
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct HeapArray<T, const N: usize> {
data: Box<[T; N]>,
}
impl <T, const N: usize> HeapArray<T, N> {
unsafe fn alloc_array() -> NonNull<[T; N]> {
let layout = Layout::new::<[T; N]>();
let pointer = alloc(layout);
if pointer.is_null() {
handle_alloc_error(layout)
} else {
NonNull::new_unchecked(pointer as *mut [T; N])
}
}
pub fn from_fn<F: FnMut(usize) -> T>(mut f: F) -> Self {
unsafe {
let array = Self::alloc_array();
let first_element = array.as_ptr() as *mut T;
for i in 0..N {
ptr::write(first_element.offset(i as isize), f(i));
}
Self {
data: Box::from_raw(array.as_ptr())
}
}
}
pub unsafe fn from_raw(pointer: *mut T) -> Self {
Self {
data: Box::from_raw(pointer as *mut [T; N])
}
}
pub fn as_ptr(&self) -> *const T {
self.data.as_ptr()
}
pub fn as_slice(&self) -> &[T] {
self.data.as_slice()
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr()
}
pub fn as_mut_slice(&mut self) -> &mut [T] {
self.data.as_mut_slice()
}
pub const fn len(&self) -> usize {
N
}
}
impl <T, const N: usize> HeapArray<MaybeUninit<T>, N> {
pub fn new_uninit() -> Self {
unsafe {
let array = Self::alloc_array();
Self {
data: Box::from_raw(array.as_ptr())
}
}
}
}
impl <T, const N: usize> Index<usize> for HeapArray<T, N> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
self.data.index(index)
}
}
impl <T, const N: usize> IndexMut<usize> for HeapArray<T, N> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.data.index_mut(index)
}
}
impl <T, const N: usize> IntoIterator for HeapArray<T, N> {
type Item = T;
type IntoIter = <[T; N] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
}
}
impl <T, const N: usize> Deref for HeapArray<T, N> {
type Target = [T];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl <T: Default, const N: usize> Default for HeapArray<T, N> {
fn default() -> Self {
Self::from_fn(|_| T::default())
}
}
impl <T, const N: usize> AsMut<[T]> for HeapArray<T, N> {
fn as_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl <T, const N: usize> AsRef<[T]> for HeapArray<T, N> {
fn as_ref(&self) -> &[T] {
self.as_slice()
}
}
impl <T, const N: usize> Borrow<[T]> for HeapArray<T, N> {
fn borrow(&self) -> &[T] {
self.as_slice()
}
}
impl <T, const N: usize> BorrowMut<[T]> for HeapArray<T, N> {
fn borrow_mut(&mut self) -> &mut [T] {
self.as_mut_slice()
}
}
impl <T, const N: usize> From<[T; N]> for HeapArray<T, N> {
fn from(value: [T; N]) -> Self {
Self {
data: Box::new(value)
}
}
}
impl <T, const N: usize> From<HeapArray<T, N>> for [T; N] {
fn from(value: HeapArray<T, N>) -> Self {
*value.data
}
}
impl <T: Clone, const N: usize> TryFrom<&[T]> for HeapArray<T, N> {
type Error = usize;
fn try_from(value: &[T]) -> Result<Self, usize> {
if value.len() == N {
Ok(Self::from_fn(|i| value[i].clone()))
} else {
Err(N)
}
}
}
impl <T: Clone, const N: usize> TryFrom<&mut [T]> for HeapArray<T, N> {
type Error = usize;
fn try_from(value: &mut [T]) -> Result<Self, usize> {
if value.len() == N {
Ok(Self::from_fn(|i| value[i].clone()))
} else {
Err(N)
}
}
}
impl <T, const N: usize> From<Box<[T; N]>> for HeapArray<T, N> {
fn from(value: Box<[T; N]>) -> Self {
Self {
data: value
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct HeapArray2D<T, const M: usize, const N: usize> {
data: Box<[[T; M]; N]>,
}
impl <T, const M: usize, const N: usize> HeapArray2D<T, M, N> {
unsafe fn alloc_array() -> NonNull<[[T; M]; N]> {
let layout = Layout::new::<[[T; M]; N]>();
let pointer = alloc(layout);
if pointer.is_null() {
handle_alloc_error(layout)
} else {
NonNull::new_unchecked(pointer as *mut [[T; M]; N])
}
}
pub fn from_fn<F: FnMut(usize, usize) -> T>(mut f: F) -> Self {
unsafe {
let array = Self::alloc_array();
let first_element = array.as_ptr() as *mut T;
for i in 0..N {
for j in 0..M {
let index = (i * M + j) as isize;
ptr::write(first_element.offset(index), f(i, j));
}
}
Self {
data: Box::from_raw(array.as_ptr())
}
}
}
pub unsafe fn from_raw(pointer: *mut T) -> Self {
Self {
data: Box::from_raw(pointer as *mut [[T; M]; N])
}
}
pub fn as_ptr(&self) -> *const T {
self.data.as_ptr() as *const T
}
pub fn as_slice(&self) -> &[[T; M]] {
self.data.as_slice()
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr() as *mut T
}
pub fn as_mut_slice(&mut self) -> &mut [[T; M]] {
self.data.as_mut_slice()
}
pub const fn outer_len(&self) -> usize {
N
}
pub const fn inner_len(&self) -> usize {
M
}
}
impl <T, const M: usize, const N: usize> HeapArray2D<MaybeUninit<T>, M, N> {
pub fn new_uninit() -> Self {
unsafe {
let array = Self::alloc_array();
Self {
data: Box::from_raw(array.as_ptr())
}
}
}
}
impl <T, const M: usize, const N: usize> Index<usize> for HeapArray2D<T, M, N> {
type Output = [T; M];
fn index(&self, index: usize) -> &Self::Output {
self.data.index(index)
}
}
impl <T, const M: usize, const N: usize> IndexMut<usize> for HeapArray2D<T, M, N> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.data.index_mut(index)
}
}
impl <T, const M: usize, const N: usize> IntoIterator for HeapArray2D<T, M, N> {
type Item = [T; M];
type IntoIter = <[[T; M]; N] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
}
}
impl <T, const M: usize, const N: usize> Deref for HeapArray2D<T, M, N> {
type Target = [[T; M]];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl <T: Default, const M: usize, const N: usize> Default for HeapArray2D<T, M, N> {
fn default() -> Self {
Self::from_fn(|_, _| T::default())
}
}
impl <T, const M: usize, const N: usize> AsMut<[[T; M]]> for HeapArray2D<T, M, N> {
fn as_mut(&mut self) -> &mut [[T; M]] {
self.as_mut_slice()
}
}
impl <T, const M: usize, const N: usize> AsRef<[[T; M]]> for HeapArray2D<T, M, N> {
fn as_ref(&self) -> &[[T; M]] {
self.as_slice()
}
}
impl <T, const M: usize, const N: usize> Borrow<[[T; M]]> for HeapArray2D<T, M, N> {
fn borrow(&self) -> &[[T; M]] {
self.as_slice()
}
}
impl <T, const M: usize, const N: usize> BorrowMut<[[T; M]]> for HeapArray2D<T, M, N> {
fn borrow_mut(&mut self) -> &mut [[T; M]] {
self.as_mut_slice()
}
}
impl <T, const M: usize, const N: usize> From<[[T; M]; N]> for HeapArray2D<T, M, N> {
fn from(value: [[T; M]; N]) -> Self {
Self {
data: Box::new(value)
}
}
}
impl <T, const M: usize, const N: usize> From<HeapArray2D<T, M, N>> for [[T; M]; N] {
fn from(value: HeapArray2D<T, M, N>) -> Self {
*value.data
}
}
impl <T: Clone, const M: usize, const N: usize> TryFrom<&[[T; M]]> for HeapArray2D<T, M, N> {
type Error = usize;
fn try_from(value: &[[T; M]]) -> Result<Self, usize> {
if value.len() == N {
Ok(Self::from_fn(|i, j| value[i][j].clone()))
} else {
Err(N)
}
}
}
impl <T: Clone, const M: usize, const N: usize> TryFrom<&mut [[T; M]]> for HeapArray2D<T, M, N> {
type Error = usize;
fn try_from(value: &mut [[T; M]]) -> Result<Self, usize> {
if value.len() == N {
Ok(Self::from_fn(|i, j| value[i][j].clone()))
} else {
Err(N)
}
}
}
impl <T, const M: usize, const N: usize> From<Box<[[T; M]; N]>> for HeapArray2D<T, M, N> {
fn from(value: Box<[[T; M]; N]>) -> Self {
Self {
data: value
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct HeapArray3D<T, const L: usize, const M: usize, const N: usize> {
data: Box<[[[T; L]; M]; N]>,
}
impl <T, const L: usize, const M: usize, const N: usize> HeapArray3D<T, L, M, N> {
unsafe fn alloc_array() -> NonNull<[[[T; L]; M]; N]> {
let layout = Layout::new::<[[[T; L]; M]; N]>();
let pointer = alloc(layout);
if pointer.is_null() {
handle_alloc_error(layout)
} else {
NonNull::new_unchecked(pointer as *mut [[[T; L]; M]; N])
}
}
pub fn from_fn<F: FnMut(usize, usize, usize) -> T>(mut f: F) -> Self {
unsafe {
let array = Self::alloc_array();
let first_element = array.as_ptr() as *mut T;
for i in 0..N {
for j in 0..M {
for k in 0..L {
let index = (i * M * L + j * L + k) as isize;
ptr::write(first_element.offset(index), f(i, j, k));
}
}
}
Self {
data: Box::from_raw(array.as_ptr())
}
}
}
pub unsafe fn from_raw(pointer: *mut T) -> Self {
Self {
data: Box::from_raw(pointer as *mut [[[T; L]; M]; N])
}
}
pub fn as_ptr(&self) -> *const T {
self.data.as_ptr() as *const T
}
pub fn as_slice(&self) -> &[[[T; L]; M]] {
self.data.as_slice()
}
pub fn as_mut_ptr(&mut self) -> *mut T {
self.data.as_mut_ptr() as *mut T
}
pub fn as_mut_slice(&mut self) -> &mut [[[T; L]; M]] {
self.data.as_mut_slice()
}
pub const fn outer_len(&self) -> usize {
N
}
pub const fn inner_len(&self) -> usize {
M
}
pub const fn innermost_len(&self) -> usize {
L
}
}
impl <T, const L: usize, const M: usize, const N: usize> HeapArray3D<MaybeUninit<T>, L, M, N> {
pub fn new_uninit() -> Self {
unsafe {
let array = Self::alloc_array();
Self {
data: Box::from_raw(array.as_ptr())
}
}
}
}
impl <T, const L: usize, const M: usize, const N: usize> Index<usize> for HeapArray3D<T, L, M, N> {
type Output = [[T; L]; M];
fn index(&self, index: usize) -> &Self::Output {
self.data.index(index)
}
}
impl <T, const L: usize, const M: usize, const N: usize> IndexMut<usize> for HeapArray3D<T, L, M, N> {
fn index_mut(&mut self, index: usize) -> &mut Self::Output {
self.data.index_mut(index)
}
}
impl <T, const L: usize, const M: usize, const N: usize> IntoIterator for HeapArray3D<T, L, M, N> {
type Item = [[T; L]; M];
type IntoIter = <[[[T; L]; M]; N] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.data.into_iter()
}
}
impl <T, const L: usize, const M: usize, const N: usize> Deref for HeapArray3D<T, L, M, N> {
type Target = [[[T; L]; M]];
fn deref(&self) -> &Self::Target {
self.as_slice()
}
}
impl <T: Default, const L: usize, const M: usize, const N: usize> Default for HeapArray3D<T, L, M, N> {
fn default() -> Self {
Self::from_fn(|_, _, _| T::default())
}
}
impl <T, const L: usize, const M: usize, const N: usize> AsMut<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
fn as_mut(&mut self) -> &mut [[[T; L]; M]] {
self.as_mut_slice()
}
}
impl <T, const L: usize, const M: usize, const N: usize> AsRef<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
fn as_ref(&self) -> &[[[T; L]; M]] {
self.as_slice()
}
}
impl <T, const L: usize, const M: usize, const N: usize> Borrow<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
fn borrow(&self) -> &[[[T; L]; M]] {
self.as_slice()
}
}
impl <T, const L: usize, const M: usize, const N: usize> BorrowMut<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
fn borrow_mut(&mut self) -> &mut [[[T; L]; M]] {
self.as_mut_slice()
}
}
impl <T, const L: usize, const M: usize, const N: usize> From<[[[T; L]; M]; N]> for HeapArray3D<T, L, M, N> {
fn from(value: [[[T; L]; M]; N]) -> Self {
Self {
data: Box::new(value)
}
}
}
impl <T, const L: usize, const M: usize, const N: usize> From<HeapArray3D<T, L, M, N>> for [[[T; L]; M]; N] {
fn from(value: HeapArray3D<T, L, M, N>) -> Self {
*value.data
}
}
impl <T: Clone, const L: usize, const M: usize, const N: usize> TryFrom<&[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
type Error = usize;
fn try_from(value: &[[[T; L]; M]]) -> Result<Self, usize> {
if value.len() == N {
Ok(Self::from_fn(|i, j, k| value[i][j][k].clone()))
} else {
Err(N)
}
}
}
impl <T: Clone, const L: usize, const M: usize, const N: usize> TryFrom<&mut [[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
type Error = usize;
fn try_from(value: &mut [[[T; L]; M]]) -> Result<Self, usize> {
if value.len() == N {
Ok(Self::from_fn(|i, j, l| value[i][j][l].clone()))
} else {
Err(N)
}
}
}
impl <T, const L: usize, const M: usize, const N: usize> From<Box<[[[T; L]; M]; N]>> for HeapArray3D<T, L, M, N> {
fn from(value: Box<[[[T; L]; M]; N]>) -> Self {
Self {
data: value
}
}
}
#[cfg(test)]
mod tests {
use crate::{HeapArray, HeapArray2D, HeapArray3D};
#[test]
fn test_from_fn() {
let array: HeapArray<usize, 3> = HeapArray::from_fn(|i| i * 10);
assert_eq!(0, array[0]);
assert_eq!(10, array[1]);
assert_eq!(20, array[2]);
}
#[test]
fn test_from_fn_2d() {
let array: HeapArray2D<usize, 3, 3> = HeapArray2D::from_fn(|i, j| i * 10 + j);
assert_eq!(0, array[0][0]);
assert_eq!(1, array[0][1]);
assert_eq!(2, array[0][2]);
assert_eq!(10, array[1][0]);
assert_eq!(11, array[1][1]);
assert_eq!(12, array[1][2]);
assert_eq!(20, array[2][0]);
assert_eq!(21, array[2][1]);
assert_eq!(22, array[2][2]);
}
#[test]
fn test_from_fn_3d() {
let array: HeapArray3D<usize, 2, 3, 3> = HeapArray3D::from_fn(|i, j, k| i * 10 + j + k * 100);
assert_eq!(0, array[0][0][0]);
assert_eq!(1, array[0][1][0]);
assert_eq!(2, array[0][2][0]);
assert_eq!(10, array[1][0][0]);
assert_eq!(11, array[1][1][0]);
assert_eq!(12, array[1][2][0]);
assert_eq!(20, array[2][0][0]);
assert_eq!(21, array[2][1][0]);
assert_eq!(22, array[2][2][0]);
assert_eq!(100, array[0][0][1]);
assert_eq!(101, array[0][1][1]);
assert_eq!(102, array[0][2][1]);
assert_eq!(110, array[1][0][1]);
assert_eq!(111, array[1][1][1]);
assert_eq!(112, array[1][2][1]);
assert_eq!(120, array[2][0][1]);
assert_eq!(121, array[2][1][1]);
assert_eq!(122, array[2][2][1]);
}
#[test]
fn test_write_index() {
let mut array: HeapArray<usize, 5> = HeapArray::default();
array[3] = 5;
assert_eq!(0, array[2]);
assert_eq!(5, array[3]);
}
#[test]
fn test_write_index_2d() {
let mut array: HeapArray2D<usize, 2, 5> = HeapArray2D::default();
array[3] = [1, 2];
assert_eq!(0, array[0][0]);
assert_eq!(1, array[3][0]);
assert_eq!(2, array[3][1]);
}
#[test]
fn test_write_index_subarray_2d() {
let mut array: HeapArray2D<usize, 2, 5> = HeapArray2D::default();
array[3] = [1, 2];
assert_eq!([0, 0], array[0]);
assert_eq!([1, 2], array[3]);
}
#[test]
fn test_write_index_3d() {
let mut array: HeapArray3D<usize, 3, 2, 5> = HeapArray3D::default();
array[3] = [[1, 2, 3], [4, 5, 6]];
assert_eq!(0, array[0][0][0]);
assert_eq!(1, array[3][0][0]);
assert_eq!(6, array[3][1][2]);
}
#[test]
fn test_write_index_subarray_3d() {
let mut array: HeapArray3D<usize, 3, 2, 5> = HeapArray3D::default();
array[3] = [[1, 2, 3], [4, 5, 6]];
assert_eq!([[0, 0, 0], [0, 0, 0]], array[0]);
assert_eq!([1, 2, 3], array[3][0]);
assert_eq!([4, 5, 6], array[3][1]);
}
#[test]
#[should_panic]
fn test_read_out_of_bounds() {
let array: HeapArray<usize, 5> = HeapArray::default();
assert_ne!(0, array[5]);
}
#[test]
#[should_panic]
fn test_read_out_of_bounds_2d() {
let array: HeapArray2D<usize, 6, 5> = HeapArray2D::default();
assert_ne!(0, array[5][0]);
}
#[test]
#[should_panic]
fn test_read_out_of_bounds_subarray_2d() {
let array: HeapArray2D<usize, 6, 5> = HeapArray2D::default();
assert_ne!([0, 0, 0, 0, 0, 0], array[5]);
}
#[test]
#[should_panic]
fn test_read_out_of_bounds_3d() {
let array: HeapArray3D<usize, 7, 6, 5> = HeapArray3D::default();
assert_ne!(0, array[5][0][0]);
}
#[test]
#[should_panic]
fn test_read_out_of_bounds_subarray_3d() {
let array: HeapArray3D<usize, 2, 6, 5> = HeapArray3D::default();
assert_ne!([[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], array[5]);
}
}