array_trait/array_nd.rs
1use super::*;
2
3/// A trait for N-dimensional arrays with depth up to 64.
4///
5/// The associated constants [DIMENSIONS](ArrayNd::DIMENSIONS) and [FLAT_LENGTH](ArrayNd::FLAT_LENGTH) vary depending on the chosen depth.
6///
7/// The assiciated type [ItemNd](ArrayNd::ItemNd) represents the innermost type given a chosen depth.
8///
9/// # Examples
10///
11/// ```rust
12/// #![feature(generic_const_exprs)]
13///
14/// use array_trait::*;
15///
16/// type Mat2x3 = [[i8; 3]; 2];
17///
18/// /// The number of dimensions
19/// const DEPTH: usize = 2;
20///
21/// // `FLAT_LENGTH` is the combined length if the N-dimensional array was flattened,
22/// // i.e. the product of the lengths of each dimension.
23/// assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::FLAT_LENGTH, 6);
24///
25/// // `DIMENSIONS` contains the lengths of each dimension ordered outermost to innermost.
26/// assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::DIMENSIONS, [2, 3]);
27/// ```
28pub trait ArrayNd<const DEPTH: usize>: Array
29{
30 /// The dimensions of the n-dimensional containing the lengths of each level of array from outermost to innermost
31 const DIMENSIONS: [usize; DEPTH];
32 /// The product of the lengths of each dimension.
33 const FLAT_LENGTH: usize;
34 type ElemNd;
35}
36
37macro_rules! count {
38 () => {0};
39 ($a:ident) => {1};
40 ($a:ident $($b:ident)+) => {1 $(+ count!($b))+};
41}
42macro_rules! flat_len {
43 () => {0};
44 ($a:ident $($b:ident)*) => {$a $(* $b)*}
45}
46
47macro_rules! nd {
48 ($t:ty;) => {
49 $t
50 };
51 ($t:ty; $a:ident) => {
52 [$t; $a]
53 };
54 ($t:ty; $a:ident $($b:ident)+) => {
55 [nd!{$t; $($b)+}; $a]
56 };
57}
58
59macro_rules! impl_nd_array {
60 ($a:ident $($($b:ident)+)?) => {
61 impl<T, const $a: usize $($(, const $b: usize)+)?> /*const*/ ArrayNd<{count!{$a $($($b)+)?}}> for nd!{T; $a $($($b)+)?}
62 {
63 const DIMENSIONS: [usize; count!{$a $($($b)+)?}] = [$a $($(, $b)+)?];
64 const FLAT_LENGTH: usize = flat_len!{$a $($($b)+)?};
65 type ElemNd = T;
66 }
67 $(impl_nd_array!($($b)+);)?
68 };
69}
70
71mod r#impl
72{
73 use super::*;
74
75 impl_nd_array!(
76 _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _10 _11 _12 _13 _14 _15 _16
77 _17 _18 _19 _20 _21 _22 _23 _24 _25 _26 _27 _28 _29 _30 _31 _32
78 _33 _34 _35 _36 _37 _38 _39 _40 _41 _42 _43 _44 _45 _46 _47 _48
79 _49 _50 _51 _52 _53 _54 _55 _56 _57 _58 _59 _60 _61 _62 _63 _64
80 );
81}
82/*
83_65 _66 _67 _68 _69 _70 _71 _72 _73 _74 _75 _76 _77 _78 _79 _80
84_81 _82 _83 _84 _85 _86 _87 _88 _89 _90 _91 _92 _93 _94 _95 _96
85_97 _98 _99 _100 _101 _102 _103 _104 _105 _106 _107 _108 _109 _110 _111 _112
86_113 _114 _115 _116 _117 _118 _119 _120 _121 _122 _123 _124 _125 _126 _127 _128
87*/
88
89#[cfg(test)]
90mod test
91{
92 #[test]
93 fn test()
94 {
95 use crate::*;
96
97 type Mat2x3 = [[i8; 3]; 2];
98
99 /// The number of dimensions
100 const DEPTH: usize = 2;
101
102 // `FLAT_LENGTH` is the combined length if the N-dimensional array was flattened
103 assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::FLAT_LENGTH, 6);
104
105 // `DIMENSIONS` contains the lengths of each dimension ordered outermost to innermost.
106 assert_eq!(<Mat2x3 as ArrayNd<DEPTH>>::DIMENSIONS, [2, 3]);
107 }
108}