static_array/
lib.rs

1//! A no-std rust crate providing a heap-allocated non-resizable type-checked array.
2// !
3//! The following types are provided:
4//! - `HeapArray` - A one dimensional heap-allocated array.
5//! - `HeapArray2D` - A two dimensional heap-allocated array.
6//! - `HeapArray3D` - A three dimensional heap-allocated array.
7//!
8//! This crate does not depend on `std` but does require `alloc` in order to create the array.
9//!
10//! # Examples
11//! ## Creating a large array on the heap using a function.
12//! ```
13//! use static_array::HeapArray;
14//!
15//! // Creates an array 16 MB (on 64 bit systems) in size which is larger than the standard linux stack size.
16//! let array: HeapArray<usize, 2000000> = HeapArray::from_fn(|i| i);
17//!
18//! assert_eq!(1247562, array[1247562]);
19//! ```
20//!
21//! ## Creating a large array from the default value of a type.
22//! ```
23//! use static_array::HeapArray;
24//!
25//! let array: HeapArray<usize, 2000000> = HeapArray::default();
26//!
27//! assert_eq!(0, array[1247562]);
28//! ```
29
30#![no_std]
31
32extern crate alloc;
33
34#[cfg(feature = "rayon")]
35use rayon::prelude::*;
36
37use core::{ptr::{NonNull, self}, alloc::Layout, mem::MaybeUninit, ops::{Index, IndexMut, Deref, DerefMut}, borrow::{Borrow, BorrowMut}};
38use alloc::{boxed::Box, alloc::{alloc, handle_alloc_error}};
39
40/// A heap allocated contiguous one dimensional array.
41/// This is equivalent in layout to the type `[T; N]`.
42///
43/// - `T` - The type of data stored in the array.
44/// - `N` - The length of the array.
45///
46/// # Examples
47/// ## Creating a large one dimensional array on the heap using a function.
48/// ```
49/// use static_array::HeapArray;
50///
51/// // Creates an array 16 MB (on 64 bit systems) in size which is larger than the standard linux stack size.
52/// let array: HeapArray<usize, 2000000> = HeapArray::from_fn(|i| i);
53///
54/// assert_eq!(1247562, array[1247562]);
55/// ```
56///
57/// ## Creating a large array from the default value of a type.
58/// ```
59/// use static_array::HeapArray;
60///
61/// let array: HeapArray<usize, 2000000> = HeapArray::default();
62///
63/// assert_eq!(0, array[1247562]);
64/// ```
65#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
66pub struct HeapArray<T, const N: usize> {
67    /// The data stored inside the array.
68    data: Box<[T; N]>,
69}
70
71impl <T, const N: usize> HeapArray<T, N> {
72    /// Allocates the heap array for this type.
73    unsafe fn alloc_array() -> NonNull<[T; N]> {
74        let layout = Layout::new::<[T; N]>();
75        
76        let pointer = alloc(layout);
77
78        if pointer.is_null() {
79            handle_alloc_error(layout)
80        } else {
81            NonNull::new_unchecked(pointer as *mut [T; N])
82        }
83    }
84
85    /// Creates a new `HeapArray` by calling a function at each index.
86    ///
87    /// - `f` - The function to call.
88    pub fn from_fn<F: FnMut(usize) -> T>(mut f: F) -> Self {
89        unsafe {
90            let array = Self::alloc_array();
91
92            let first_element = array.as_ptr() as *mut T;
93
94            for i in 0..N {
95                ptr::write(first_element.offset(i as isize), f(i));
96            }
97
98            Self {
99                data: Box::from_raw(array.as_ptr())
100            }
101        }
102    }
103    
104    /// Creates a new `HeapArray` by calling a function at each index in parallel.
105    ///
106    /// - `f` - The function to call.
107    #[cfg(feature = "rayon")]
108    pub fn from_fn_par<F: Fn(usize) -> T + Send + Sync>(f: F) -> Self where T: Send + Sync {
109        unsafe {
110            let mut array = HeapArray::alloc_array();
111            
112            array.as_mut().into_par_iter().enumerate().for_each(|(i, value)| {
113                ptr::write_volatile(value, f(i))
114            });
115
116            Self {
117                data: Box::from_raw(array.as_ptr())
118            }
119        }
120    }
121
122    /// Creates a new `HeapArray` from a raw pointer.
123    ///
124    /// - `pointer` - The pointer containing the array data.
125    ///
126    /// # Safety
127    /// To safely call this method the following constraints must be maintained:
128    /// - The pointer must not be null.
129    /// - The pointer must point to a region of memory at least as large as the array size.
130    /// - The portion of the region pointed to by the pointer must be initialised up to the length
131    /// of the array.
132    pub unsafe fn from_raw(pointer: *mut T) -> Self {
133        Self {
134            data: Box::from_raw(pointer as *mut [T; N])
135        }
136    } 
137
138    /// Returns a raw pointer to the data contained in this array
139    pub fn as_ptr(&self) -> *const T {
140        self.data.as_ptr()
141    }
142
143    /// Returns a slice containing the array elements.
144    pub fn as_slice(&self) -> &[T] {
145        self.data.as_slice()
146    }
147    
148    /// Returns a raw mutable pointer to the data contained in this array
149    pub fn as_mut_ptr(&mut self) -> *mut T {
150        self.data.as_mut_ptr()
151    }
152
153    /// Returns a mutable slice containing the array elements.
154    pub fn as_mut_slice(&mut self) -> &mut [T] {
155        self.data.as_mut_slice()
156    }
157
158    /// Returns the length of the array.
159    pub const fn len(&self) -> usize {
160        N
161    }
162}
163
164impl <T, const N: usize> HeapArray<MaybeUninit<T>, N> {
165    /// Creates a new uninitialised heap array.
166    pub fn new_uninit() -> Self {
167        unsafe {
168            let array = Self::alloc_array();
169
170            Self {
171                data: Box::from_raw(array.as_ptr())
172            }
173        }
174    }
175}
176
177impl <T, const N: usize> Index<usize> for HeapArray<T, N> {
178    type Output = T;
179
180    fn index(&self, index: usize) -> &Self::Output {
181        self.data.index(index)
182    }
183}
184
185impl <T, const N: usize> IndexMut<usize> for HeapArray<T, N> {
186    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
187        self.data.index_mut(index)
188    }
189}
190
191impl <T, const N: usize> IntoIterator for HeapArray<T, N> {
192    type Item = T;
193
194    type IntoIter = <[T; N] as IntoIterator>::IntoIter;
195
196    fn into_iter(self) -> Self::IntoIter {
197        self.data.into_iter()
198    }
199}
200
201impl <T, const N: usize> Deref for HeapArray<T, N> {
202    type Target = [T];
203
204    fn deref(&self) -> &Self::Target {
205        self.as_slice()
206    }
207}
208
209impl <T, const N: usize> DerefMut for HeapArray<T, N> {
210    fn deref_mut(&mut self) -> &mut Self::Target {
211        self.as_mut_slice()
212    }
213}
214
215impl <T: Default, const N: usize> Default for HeapArray<T, N> {
216    fn default() -> Self {
217        Self::from_fn(|_| T::default())
218    }
219}
220
221impl <T, const N: usize> AsMut<[T]> for HeapArray<T, N> {
222    fn as_mut(&mut self) -> &mut [T] {
223        self.as_mut_slice()
224    }
225}
226
227impl <T, const N: usize> AsRef<[T]> for HeapArray<T, N> {
228    fn as_ref(&self) -> &[T] {
229        self.as_slice()
230    }
231}
232
233impl <T, const N: usize> Borrow<[T]> for HeapArray<T, N> {
234    fn borrow(&self) -> &[T] {
235        self.as_slice()
236    }
237}
238
239impl <T, const N: usize> BorrowMut<[T]> for HeapArray<T, N> {
240    fn borrow_mut(&mut self) -> &mut [T] {
241        self.as_mut_slice()
242    }
243}
244
245impl <T, const N: usize> From<[T; N]> for HeapArray<T, N> {
246    fn from(value: [T; N]) -> Self {
247        Self {
248            data: Box::new(value)
249        }
250    }
251}
252
253impl <T, const N: usize> From<HeapArray<T, N>> for [T; N] {
254    fn from(value: HeapArray<T, N>) -> Self {
255        *value.data
256    }
257}
258
259impl <T: Clone, const N: usize> TryFrom<&[T]> for HeapArray<T, N> {
260    type Error = usize;
261
262    fn try_from(value: &[T]) -> Result<Self, usize> {
263        if value.len() == N {
264            Ok(Self::from_fn(|i| value[i].clone()))
265        } else {
266            Err(N)
267        }
268    }
269}
270
271impl <T: Clone, const N: usize> TryFrom<&mut [T]> for HeapArray<T, N> {
272    type Error = usize;
273
274    fn try_from(value: &mut [T]) -> Result<Self, usize> {
275        if value.len() == N {
276            Ok(Self::from_fn(|i| value[i].clone()))
277        } else {
278            Err(N)
279        }
280    }
281}
282
283impl <T, const N: usize> From<Box<[T; N]>> for HeapArray<T, N> {
284    fn from(value: Box<[T; N]>) -> Self {
285        Self {
286            data: value
287        }
288    }
289}
290
291/// A heap allocated contiguous two dimensional array.
292/// This is equivalent to the type `[[T; M]; N]`.
293///
294/// - `T` - The type of data stored in the array.
295/// - `M` - The length of the inner array.
296/// - `N` - The length of the array.
297///
298/// # Examples
299/// ## Creating a large two dimensional array on the heap using a function.
300/// ```
301/// use static_array::HeapArray2D;
302///
303/// let array: HeapArray2D<usize, 1000, 1000> = HeapArray2D::from_fn(|i, j| i * j);
304///
305/// assert_eq!(10000, array[100][100]);
306/// ```
307///
308/// ## Creating a large two dimensional array from the default value of a type.
309/// ```
310/// use static_array::HeapArray2D;
311///
312/// let array: HeapArray2D<usize, 1000, 1000> = HeapArray2D::default();
313///
314/// assert_eq!(0, array[100][100]);
315/// ```
316#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
317pub struct HeapArray2D<T, const M: usize, const N: usize> {
318    /// The data stored inside the array.
319    data: Box<[[T; M]; N]>,
320}
321
322impl <T, const M: usize, const N: usize> HeapArray2D<T, M, N> {
323    /// Allocates the heap array for this type.
324    unsafe fn alloc_array() -> NonNull<[[T; M]; N]> {
325        let layout = Layout::new::<[[T; M]; N]>();
326        
327        let pointer = alloc(layout);
328
329        if pointer.is_null() {
330            handle_alloc_error(layout)
331        } else {
332            NonNull::new_unchecked(pointer as *mut [[T; M]; N])
333        }
334    }
335
336    /// Creates a new `HeapArray2D` by calling a function at each index.
337    ///
338    /// - `f` - The function to call.
339    pub fn from_fn<F: FnMut(usize, usize) -> T>(mut f: F) -> Self {
340        unsafe {
341            let array = Self::alloc_array();
342
343            let first_element = array.as_ptr() as *mut T;
344
345            for i in 0..N {
346                for j in 0..M {
347                    let index = (i * M + j) as isize;
348
349                    ptr::write(first_element.offset(index), f(i, j));
350                }
351            }
352
353            Self {
354                data: Box::from_raw(array.as_ptr())
355            }
356        }
357    }
358    
359    /// Creates a new `HeapArray2D` by calling a function at each index in parallel.
360    ///
361    /// - `f` - The function to call.
362    #[cfg(feature = "rayon")]
363    pub fn from_fn_par<F: Fn(usize, usize) -> T + Send + Sync>(f: F) -> Self where T: Send + Sync {
364        unsafe {
365            let mut array = HeapArray2D::alloc_array();
366            
367            array.as_mut().into_par_iter().enumerate().for_each(|(i, value)| {
368                let pointer = value as *mut T;
369
370                for j in 0..M {
371                    ptr::write_volatile(pointer.offset(j as isize), f(i, j));
372                }
373            });
374
375            Self {
376                data: Box::from_raw(array.as_ptr())
377            }
378        }
379    }
380
381    /// Creates a new `HeapArray2D` from a raw pointer.
382    ///
383    /// - `pointer` - The pointer containing the array data.
384    ///
385    /// # Safety
386    /// To safely call this method the following constraints must be maintained:
387    /// - The pointer must not be null.
388    /// - The pointer must point to a region of memory at least as large as the array size.
389    /// - The portion of the region pointed to by the pointer must be initialised up to the length
390    /// of the array.
391    pub unsafe fn from_raw(pointer: *mut T) -> Self {
392        Self {
393            data: Box::from_raw(pointer as *mut [[T; M]; N])
394        }
395    } 
396
397    /// Returns a raw pointer to the data contained in this array
398    pub fn as_ptr(&self) -> *const T {
399        self.data.as_ptr() as *const T
400    }
401
402    /// Returns a slice containing the array elements.
403    pub fn as_slice(&self) -> &[[T; M]] {
404        self.data.as_slice()
405    }
406    
407    /// Returns a raw mutable pointer to the data contained in this array
408    pub fn as_mut_ptr(&mut self) -> *mut T {
409        self.data.as_mut_ptr() as *mut T
410    }
411
412    /// Returns a mutable slice containing the array elements.
413    pub fn as_mut_slice(&mut self) -> &mut [[T; M]] {
414        self.data.as_mut_slice()
415    }
416
417    /// Returns the length of the outer array.
418    pub const fn outer_len(&self) -> usize {
419        N
420    }
421    
422    /// Returns the length of the inner array.
423    pub const fn inner_len(&self) -> usize {
424        M
425    }
426}
427
428impl <T, const M: usize, const N: usize> HeapArray2D<MaybeUninit<T>, M, N> {
429    /// Creates a new uninitialised heap array.
430    pub fn new_uninit() -> Self {
431        unsafe {
432            let array = Self::alloc_array();
433
434            Self {
435                data: Box::from_raw(array.as_ptr())
436            }
437        }
438    }
439}
440
441impl <T, const M: usize, const N: usize> Index<usize> for HeapArray2D<T, M, N> {
442    type Output = [T; M];
443
444    fn index(&self, index: usize) -> &Self::Output {
445        self.data.index(index)
446    }
447}
448
449impl <T, const M: usize, const N: usize> IndexMut<usize> for HeapArray2D<T, M, N> {
450    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
451        self.data.index_mut(index)
452    }
453}
454
455impl <T, const M: usize, const N: usize> IntoIterator for HeapArray2D<T, M, N> {
456    type Item = [T; M];
457
458    type IntoIter = <[[T; M]; N] as IntoIterator>::IntoIter;
459
460    fn into_iter(self) -> Self::IntoIter {
461        self.data.into_iter()
462    }
463}
464
465impl <T, const M: usize, const N: usize> Deref for HeapArray2D<T, M, N> {
466    type Target = [[T; M]];
467
468    fn deref(&self) -> &Self::Target {
469        self.as_slice()
470    }
471}
472
473impl <T, const M: usize, const N: usize> DerefMut for HeapArray2D<T, M, N> {
474    fn deref_mut(&mut self) -> &mut Self::Target {
475        self.as_mut_slice()
476    }
477}
478
479impl <T: Default, const M: usize, const N: usize> Default for HeapArray2D<T, M, N> {
480    fn default() -> Self {
481        Self::from_fn(|_, _| T::default())
482    }
483}
484
485impl <T, const M: usize, const N: usize> AsMut<[[T; M]]> for HeapArray2D<T, M, N> {
486    fn as_mut(&mut self) -> &mut [[T; M]] {
487        self.as_mut_slice()
488    }
489}
490
491impl <T, const M: usize, const N: usize> AsRef<[[T; M]]> for HeapArray2D<T, M, N> {
492    fn as_ref(&self) -> &[[T; M]] {
493        self.as_slice()
494    }
495}
496
497impl <T, const M: usize, const N: usize> Borrow<[[T; M]]> for HeapArray2D<T, M, N> {
498    fn borrow(&self) -> &[[T; M]] {
499        self.as_slice()
500    }
501}
502
503impl <T, const M: usize, const N: usize> BorrowMut<[[T; M]]> for HeapArray2D<T, M, N> {
504    fn borrow_mut(&mut self) -> &mut [[T; M]] {
505        self.as_mut_slice()
506    }
507}
508
509impl <T, const M: usize, const N: usize> From<[[T; M]; N]> for HeapArray2D<T, M, N> {
510    fn from(value: [[T; M]; N]) -> Self {
511        Self {
512            data: Box::new(value)
513        }
514    }
515}
516
517impl <T, const M: usize, const N: usize> From<HeapArray2D<T, M, N>> for [[T; M]; N] {
518    fn from(value: HeapArray2D<T, M, N>) -> Self {
519        *value.data
520    }
521}
522
523impl <T: Clone, const M: usize, const N: usize> TryFrom<&[[T; M]]> for HeapArray2D<T, M, N> {
524    type Error = usize;
525
526    fn try_from(value: &[[T; M]]) -> Result<Self, usize> {
527        if value.len() == N {
528            Ok(Self::from_fn(|i, j| value[i][j].clone()))
529        } else {
530            Err(N)
531        }
532    }
533}
534
535impl <T: Clone, const M: usize, const N: usize> TryFrom<&mut [[T; M]]> for HeapArray2D<T, M, N> {
536    type Error = usize;
537
538    fn try_from(value: &mut [[T; M]]) -> Result<Self, usize> {
539        if value.len() == N {
540            Ok(Self::from_fn(|i, j| value[i][j].clone()))
541        } else {
542            Err(N)
543        }
544    }
545}
546
547impl <T, const M: usize, const N: usize> From<Box<[[T; M]; N]>> for HeapArray2D<T, M, N> {
548    fn from(value: Box<[[T; M]; N]>) -> Self {
549        Self {
550            data: value
551        }
552    }
553}
554
555/// A heap allocated contiguous three dimensional array.
556/// This is equivalent to the type `[[[T; L]; M]; N]`.
557///
558/// - `T` - The type of data stored in the array.
559/// - `L` - The length of the innermost array.
560/// - `M` - The length of the inner array.
561/// - `N` - The length of the array.
562///
563/// # Examples
564/// ## Creating a large three dimensional array on the heap using a function.
565/// ```
566/// use static_array::HeapArray3D;
567///
568/// let array: HeapArray3D<usize, 200, 200, 200> = HeapArray3D::from_fn(|i, j, k| i * j + k);
569///
570/// assert_eq!(10100, array[100][100][100]);
571/// ```
572///
573/// ## Creating a large three dimensional array from the default value of a type.
574/// ```
575/// use static_array::HeapArray3D;
576///
577/// let array: HeapArray3D<usize, 200, 200, 200> = HeapArray3D::default();
578///
579/// assert_eq!(0, array[100][100][100]);
580/// ```
581#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
582pub struct HeapArray3D<T, const L: usize, const M: usize, const N: usize> {
583    /// The data stored inside the array.
584    data: Box<[[[T; L]; M]; N]>,
585}
586
587impl <T, const L: usize, const M: usize, const N: usize> HeapArray3D<T, L, M, N> {
588    /// Allocates the heap array for this type.
589    unsafe fn alloc_array() -> NonNull<[[[T; L]; M]; N]> {
590        let layout = Layout::new::<[[[T; L]; M]; N]>();
591        
592        let pointer = alloc(layout);
593
594        if pointer.is_null() {
595            handle_alloc_error(layout)
596        } else {
597            NonNull::new_unchecked(pointer as *mut [[[T; L]; M]; N])
598        }
599    }
600
601    /// Creates a new `HeapArray3D` by calling a function at each index.
602    ///
603    /// - `f` - The function to call.
604    pub fn from_fn<F: FnMut(usize, usize, usize) -> T>(mut f: F) -> Self {
605        unsafe {
606            let array = Self::alloc_array();
607
608            let first_element = array.as_ptr() as *mut T;
609
610            for i in 0..N {
611                for j in 0..M {
612                    for k in 0..L {
613                        let index = (i * M * L + j * L + k) as isize;
614
615                        ptr::write(first_element.offset(index), f(i, j, k));
616                    }
617                }
618            }
619
620            Self {
621                data: Box::from_raw(array.as_ptr())
622            }
623        }
624    }
625    
626    /// Creates a new `HeapArray3D` by calling a function at each index in parallel.
627    ///
628    /// - `f` - The function to call.
629    #[cfg(feature = "rayon")]
630    pub fn from_fn_par<F: Fn(usize, usize, usize) -> T + Send + Sync>(f: F) -> Self where T: Send + Sync {
631        unsafe {
632            let mut array = HeapArray3D::alloc_array();
633            
634            array.as_mut().into_par_iter().enumerate().for_each(|(i, value)| {
635                let pointer = value as *mut [T; L] as *mut T;
636
637                for j in 0..M {
638                    for k in 0..L {
639                        let index = (j * L + k) as isize;
640
641                        ptr::write_volatile(pointer.offset(index), f(i, j, k));
642                    }
643                }
644            });
645
646            Self {
647                data: Box::from_raw(array.as_ptr())
648            }
649        }
650    }
651
652    /// Creates a new `HeapArray2D` from a raw pointer.
653    ///
654    /// - `pointer` - The pointer containing the array data.
655    ///
656    /// # Safety
657    /// To safely call this method the following constraints must be maintained:
658    /// - The pointer must not be null.
659    /// - The pointer must point to a region of memory at least as large as the array size.
660    /// - The portion of the region pointed to by the pointer must be initialised up to the length
661    /// of the array.
662    pub unsafe fn from_raw(pointer: *mut T) -> Self {
663        Self {
664            data: Box::from_raw(pointer as *mut [[[T; L]; M]; N])
665        }
666    } 
667
668    /// Returns a raw pointer to the data contained in this array
669    pub fn as_ptr(&self) -> *const T {
670        self.data.as_ptr() as *const T
671    }
672
673    /// Returns a slice containing the array elements.
674    pub fn as_slice(&self) -> &[[[T; L]; M]] {
675        self.data.as_slice()
676    }
677    
678    /// Returns a raw mutable pointer to the data contained in this array
679    pub fn as_mut_ptr(&mut self) -> *mut T {
680        self.data.as_mut_ptr() as *mut T
681    }
682
683    /// Returns a mutable slice containing the array elements.
684    pub fn as_mut_slice(&mut self) -> &mut [[[T; L]; M]] {
685        self.data.as_mut_slice()
686    }
687
688    /// Returns the length of the outer array.
689    pub const fn outer_len(&self) -> usize {
690        N
691    }
692    
693    /// Returns the length of the inner array.
694    pub const fn inner_len(&self) -> usize {
695        M
696    }
697    
698    /// Returns the length of the innermost array.
699    pub const fn innermost_len(&self) -> usize {
700        L
701    }
702}
703
704impl <T, const L: usize, const M: usize, const N: usize> HeapArray3D<MaybeUninit<T>, L, M, N> {
705    /// Creates a new uninitialised heap array.
706    pub fn new_uninit() -> Self {
707        unsafe {
708            let array = Self::alloc_array();
709
710            Self {
711                data: Box::from_raw(array.as_ptr())
712            }
713        }
714    }
715}
716
717impl <T, const L: usize, const M: usize, const N: usize> Index<usize> for HeapArray3D<T, L, M, N> {
718    type Output = [[T; L]; M];
719
720    fn index(&self, index: usize) -> &Self::Output {
721        self.data.index(index)
722    }
723}
724
725impl <T, const L: usize, const M: usize, const N: usize> IndexMut<usize> for HeapArray3D<T, L, M, N> {
726    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
727        self.data.index_mut(index)
728    }
729}
730
731impl <T, const L: usize, const M: usize, const N: usize> IntoIterator for HeapArray3D<T, L, M, N> {
732    type Item = [[T; L]; M];
733
734    type IntoIter = <[[[T; L]; M]; N] as IntoIterator>::IntoIter;
735
736    fn into_iter(self) -> Self::IntoIter {
737        self.data.into_iter()
738    }
739}
740
741impl <T, const L: usize, const M: usize, const N: usize> Deref for HeapArray3D<T, L, M, N> {
742    type Target = [[[T; L]; M]];
743
744    fn deref(&self) -> &Self::Target {
745        self.as_slice()
746    }
747}
748
749impl <T, const L: usize, const M: usize, const N: usize> DerefMut for HeapArray3D<T, L, M, N> {
750    fn deref_mut(&mut self) -> &mut Self::Target {
751        self.as_mut_slice()
752    }
753}
754
755impl <T: Default, const L: usize, const M: usize, const N: usize> Default for HeapArray3D<T, L, M, N> {
756    fn default() -> Self {
757        Self::from_fn(|_, _, _| T::default())
758    }
759}
760
761impl <T, const L: usize, const M: usize, const N: usize> AsMut<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
762    fn as_mut(&mut self) -> &mut [[[T; L]; M]] {
763        self.as_mut_slice()
764    }
765}
766
767impl <T, const L: usize, const M: usize, const N: usize> AsRef<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
768    fn as_ref(&self) -> &[[[T; L]; M]] {
769        self.as_slice()
770    }
771}
772
773impl <T, const L: usize, const M: usize, const N: usize> Borrow<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
774    fn borrow(&self) -> &[[[T; L]; M]] {
775        self.as_slice()
776    }
777}
778
779impl <T, const L: usize, const M: usize, const N: usize> BorrowMut<[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
780    fn borrow_mut(&mut self) -> &mut [[[T; L]; M]] {
781        self.as_mut_slice()
782    }
783}
784
785impl <T, const L: usize, const M: usize, const N: usize> From<[[[T; L]; M]; N]> for HeapArray3D<T, L, M, N> {
786    fn from(value: [[[T; L]; M]; N]) -> Self {
787        Self {
788            data: Box::new(value)
789        }
790    }
791}
792
793impl <T, const L: usize, const M: usize, const N: usize> From<HeapArray3D<T, L, M, N>> for [[[T; L]; M]; N] {
794    fn from(value: HeapArray3D<T, L, M, N>) -> Self {
795        *value.data
796    }
797}
798
799impl <T: Clone, const L: usize, const M: usize, const N: usize> TryFrom<&[[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
800    type Error = usize;
801
802    fn try_from(value: &[[[T; L]; M]]) -> Result<Self, usize> {
803        if value.len() == N {
804            Ok(Self::from_fn(|i, j, k| value[i][j][k].clone()))
805        } else {
806            Err(N)
807        }
808    }
809}
810
811impl <T: Clone, const L: usize, const M: usize, const N: usize> TryFrom<&mut [[[T; L]; M]]> for HeapArray3D<T, L, M, N> {
812    type Error = usize;
813
814    fn try_from(value: &mut [[[T; L]; M]]) -> Result<Self, usize> {
815        if value.len() == N {
816            Ok(Self::from_fn(|i, j, l| value[i][j][l].clone()))
817        } else {
818            Err(N)
819        }
820    }
821}
822
823impl <T, const L: usize, const M: usize, const N: usize> From<Box<[[[T; L]; M]; N]>> for HeapArray3D<T, L, M, N> {
824    fn from(value: Box<[[[T; L]; M]; N]>) -> Self {
825        Self {
826            data: value
827        }
828    }
829}
830
831#[cfg(test)]
832mod tests {
833    use crate::{HeapArray, HeapArray2D, HeapArray3D};
834
835    #[test]
836    fn test_from_fn() {
837        let array: HeapArray<usize, 3> = HeapArray::from_fn(|i| i * 10);
838
839        assert_eq!(0, array[0]);
840        assert_eq!(10, array[1]);
841        assert_eq!(20, array[2]);
842    }
843    
844    #[test]
845    #[cfg(feature = "rayon")]
846    fn test_from_fn_par() {
847        let array: HeapArray<usize, 100> = HeapArray::from_fn_par(|i| i * 10);
848
849        assert_eq!(0, array[0]);
850        assert_eq!(10, array[1]);
851        assert_eq!(20, array[2]);
852    }
853
854    #[test]
855    fn test_from_fn_2d() {
856        let array: HeapArray2D<usize, 3, 3> = HeapArray2D::from_fn(|i, j| i * 10 + j);
857
858        assert_eq!(0, array[0][0]);
859        assert_eq!(1, array[0][1]);
860        assert_eq!(2, array[0][2]);
861        assert_eq!(10, array[1][0]);
862        assert_eq!(11, array[1][1]);
863        assert_eq!(12, array[1][2]);
864        assert_eq!(20, array[2][0]);
865        assert_eq!(21, array[2][1]);
866        assert_eq!(22, array[2][2]);
867    }
868    
869    #[test]
870    #[cfg(feature = "rayon")]
871    fn test_from_fn_par_2d() {
872        let array: HeapArray2D<usize, 300, 300> = HeapArray2D::from_fn_par(|i, j| i * 10 + j);
873
874        assert_eq!(0, array[0][0]);
875        assert_eq!(1, array[0][1]);
876        assert_eq!(2, array[0][2]);
877        assert_eq!(10, array[1][0]);
878        assert_eq!(11, array[1][1]);
879        assert_eq!(12, array[1][2]);
880        assert_eq!(20, array[2][0]);
881        assert_eq!(21, array[2][1]);
882        assert_eq!(22, array[2][2]);
883    }
884
885    #[test]
886    fn test_from_fn_3d() {
887        let array: HeapArray3D<usize, 2, 3, 3> = HeapArray3D::from_fn(|i, j, k| i * 10 + j + k * 100);
888
889        assert_eq!(0, array[0][0][0]);
890        assert_eq!(1, array[0][1][0]);
891        assert_eq!(2, array[0][2][0]);
892        assert_eq!(10, array[1][0][0]);
893        assert_eq!(11, array[1][1][0]);
894        assert_eq!(12, array[1][2][0]);
895        assert_eq!(20, array[2][0][0]);
896        assert_eq!(21, array[2][1][0]);
897        assert_eq!(22, array[2][2][0]);
898        
899        assert_eq!(100, array[0][0][1]);
900        assert_eq!(101, array[0][1][1]);
901        assert_eq!(102, array[0][2][1]);
902        assert_eq!(110, array[1][0][1]);
903        assert_eq!(111, array[1][1][1]);
904        assert_eq!(112, array[1][2][1]);
905        assert_eq!(120, array[2][0][1]);
906        assert_eq!(121, array[2][1][1]);
907        assert_eq!(122, array[2][2][1]);
908    }
909    
910    #[test]
911    #[cfg(feature = "rayon")]
912    fn test_from_fn_par_3d() {
913        let array: HeapArray3D<usize, 200, 300, 300> = HeapArray3D::from_fn_par(|i, j, k| i * 10 + j + k * 100);
914
915        assert_eq!(0, array[0][0][0]);
916        assert_eq!(1, array[0][1][0]);
917        assert_eq!(2, array[0][2][0]);
918        assert_eq!(10, array[1][0][0]);
919        assert_eq!(11, array[1][1][0]);
920        assert_eq!(12, array[1][2][0]);
921        assert_eq!(20, array[2][0][0]);
922        assert_eq!(21, array[2][1][0]);
923        assert_eq!(22, array[2][2][0]);
924        
925        assert_eq!(100, array[0][0][1]);
926        assert_eq!(101, array[0][1][1]);
927        assert_eq!(102, array[0][2][1]);
928        assert_eq!(110, array[1][0][1]);
929        assert_eq!(111, array[1][1][1]);
930        assert_eq!(112, array[1][2][1]);
931        assert_eq!(120, array[2][0][1]);
932        assert_eq!(121, array[2][1][1]);
933        assert_eq!(122, array[2][2][1]);
934    }
935
936    #[test]
937    fn test_write_index() {
938        let mut array: HeapArray<usize, 5> = HeapArray::default();
939
940        array[3] = 5;
941
942        assert_eq!(0, array[2]);
943        assert_eq!(5, array[3]);
944    }
945    
946    #[test]
947    fn test_write_index_2d() {
948        let mut array: HeapArray2D<usize, 2, 5> = HeapArray2D::default();
949
950        array[3] = [1, 2];
951
952        assert_eq!(0, array[0][0]);
953        assert_eq!(1, array[3][0]);
954        assert_eq!(2, array[3][1]);
955    }
956    
957    #[test]
958    fn test_write_index_subarray_2d() {
959        let mut array: HeapArray2D<usize, 2, 5> = HeapArray2D::default();
960
961        array[3] = [1, 2];
962
963        assert_eq!([0, 0], array[0]);
964        assert_eq!([1, 2], array[3]);
965    }
966    
967    #[test]
968    fn test_write_index_3d() {
969        let mut array: HeapArray3D<usize, 3, 2, 5> = HeapArray3D::default();
970
971        array[3] = [[1, 2, 3], [4, 5, 6]];
972
973        assert_eq!(0, array[0][0][0]);
974        assert_eq!(1, array[3][0][0]);
975        assert_eq!(6, array[3][1][2]);
976    }
977    
978    #[test]
979    fn test_write_index_subarray_3d() {
980        let mut array: HeapArray3D<usize, 3, 2, 5> = HeapArray3D::default();
981
982        array[3] = [[1, 2, 3], [4, 5, 6]];
983
984        assert_eq!([[0, 0, 0], [0, 0, 0]], array[0]);
985        assert_eq!([1, 2, 3], array[3][0]);
986        assert_eq!([4, 5, 6], array[3][1]);
987    }
988    
989    #[test]
990    #[should_panic]
991    fn test_read_out_of_bounds() {
992        let array: HeapArray<usize, 5> = HeapArray::default();
993
994        assert_ne!(0, array[5]);
995    }
996    
997    #[test]
998    #[should_panic]
999    fn test_read_out_of_bounds_2d() {
1000        let array: HeapArray2D<usize, 6, 5> = HeapArray2D::default();
1001
1002        assert_ne!(0, array[5][0]);
1003    }
1004   
1005    #[test]
1006    #[should_panic]
1007    fn test_read_out_of_bounds_subarray_2d() {
1008        let array: HeapArray2D<usize, 6, 5> = HeapArray2D::default();
1009
1010        assert_ne!([0, 0, 0, 0, 0, 0], array[5]);
1011    }
1012    
1013    #[test]
1014    #[should_panic]
1015    fn test_read_out_of_bounds_3d() {
1016        let array: HeapArray3D<usize, 7, 6, 5> = HeapArray3D::default();
1017
1018        assert_ne!(0, array[5][0][0]);
1019    }
1020   
1021    #[test]
1022    #[should_panic]
1023    fn test_read_out_of_bounds_subarray_3d() {
1024        let array: HeapArray3D<usize, 2, 6, 5> = HeapArray3D::default();
1025
1026        assert_ne!([[0, 0], [0, 0], [0, 0], [0, 0], [0, 0], [0, 0]], array[5]);
1027    }
1028}
1029