1use crate::{Empty, Length, NotEmpty};
2use std::marker::PhantomData;
3use std::mem::size_of;
4use traits::*;
5
6pub(crate) mod traits;
7
8pub const fn size_of_val<T>(_: &T) -> usize {
9 size_of::<T>()
10}
11
12pub struct Node<V, N = Empty> {
14 value: PhantomData<V>,
15 next: PhantomData<N>,
16}
17
18#[repr(transparent)]
19pub struct Array<const N: usize, F, B> {
20 data: [u8; N], forward: PhantomData<F>,
22 backward: PhantomData<B>,
23}
24
25impl Array<0, Empty, Empty> {
26 pub const fn new<const N: usize>() -> Array<N, Empty, Empty> {
27 Array {
28 data: [0; N],
29 forward: PhantomData,
30 backward: PhantomData,
31 }
32 }
33}
34
35impl<const N: usize, F: ArrayAppend + Length, B: MemorySize + RemoveFirst> Array<N, F, B> {
36 pub fn push<V>(mut self, value: V) -> Array<N, F::Output<V>, Node<V, B>> {
37 assert!(
38 size_of::<V>() + B::SIZE <= N,
39 "The element doesn't fit in the array"
40 );
41 unsafe { self.data.as_mut_ptr().add(B::SIZE).cast::<V>().write(value) };
44 let Array { data, .. } = self;
45
46 Array {
47 data,
48 forward: PhantomData,
49 backward: PhantomData,
50 }
51 }
52
53 pub const fn forward(&self) -> RefIterator<'_, F, Empty, Self> {
54 RefIterator::new_forward(self)
55 }
56
57 pub const fn backward(&self) -> RefIterator<'_, B::Element, B::Rest, Self> {
58 RefIterator::new_backward(self)
59 }
60
61 pub const fn len(&self) -> usize {
62 F::SIZE
63 }
64
65 pub const fn is_empty(&self) -> bool {
66 F::SIZE == 0
67 }
68}
69
70pub struct RefIterator<'a, CF, CB, A> {
71 array: &'a A,
72 current_foreward: PhantomData<CF>,
73 current_backward: PhantomData<CB>,
74}
75
76impl RefIterator<'static, Empty, Empty, Empty> {
77 const fn new_forward<const N: usize, F, B>(
78 array: &Array<N, F, B>,
79 ) -> RefIterator<'_, F, Empty, Array<N, F, B>> {
80 RefIterator {
81 array,
82 current_foreward: PhantomData,
83 current_backward: PhantomData,
84 }
85 }
86
87 const fn new_backward<const N: usize, F, B: RemoveFirst>(
88 array: &Array<N, F, B>,
89 ) -> RefIterator<'_, B::Element, B::Rest, Array<N, F, B>> {
90 RefIterator {
91 array,
92 current_foreward: PhantomData,
93 current_backward: PhantomData,
94 }
95 }
96}
97
98impl<'a, A, CFV, CFN: NotEmpty, CB> RefIterator<'a, Node<CFV, CFN>, CB, A> {
99 pub const fn next(self) -> RefIterator<'a, CFN, Node<CFV, CB>, A> {
100 let RefIterator { array, .. } = self;
101
102 RefIterator {
103 array,
104 current_foreward: PhantomData,
105 current_backward: PhantomData,
106 }
107 }
108}
109
110impl<'a, A, CF, CBV, CBN> RefIterator<'a, CF, Node<CBV, CBN>, A> {
111 pub const fn prev(self) -> RefIterator<'a, Node<CBV, CF>, CBN, A> {
112 let RefIterator { array, .. } = self;
113
114 RefIterator {
115 array,
116 current_foreward: PhantomData,
117 current_backward: PhantomData,
118 }
119 }
120}
121impl<'a, const N: usize, F, B, CFV, CFN, CB: MemorySize>
122 RefIterator<'a, Node<CFV, CFN>, CB, Array<N, F, B>>
123{
124 pub const fn index(&self) -> usize {
125 CB::SIZE
126 }
127
128 pub fn value(&self) -> &CFV {
129 unsafe {
130 self.array
132 .data
133 .as_ptr()
134 .add(self.index())
135 .cast::<CFV>()
136 .as_ref()
137 .unwrap_unchecked()
138 }
139 }
140}
141
142impl<'a, const N: usize, F, B: RemoveFirst, CFV, CFN, CB: MemorySize>
143 RefIterator<'a, Node<CFV, CFN>, CB, Array<N, F, B>>
144{
145 pub const fn forward(self) -> RefIterator<'a, F, Empty, Array<N, F, B>> {
146 RefIterator::new_forward(self.array)
147 }
148
149 pub const fn backward(self) -> RefIterator<'a, B::Element, B::Rest, Array<N, F, B>> {
150 RefIterator::new_backward(self.array)
151 }
152}
153
154#[macro_export]
155macro_rules! array {
156 ($($x:expr),+ $(,)?) => {{
157 const N: usize = 0 $(+ $crate::array::size_of_val(&$x))+;
158 Array::new::<N>()$(.push($x))+
159 }};
160}
161
162#[cfg(test)]
163mod tests {
164 use super::*;
165
166 #[test]
167 fn works_1() {
168 let list = Array::new::<4>().push(10);
169
170 assert_eq!(list.forward().value(), &10);
171 assert_eq!(list.backward().value(), &10);
172
173 assert_eq!(list.forward().index(), 0);
174
175 assert_eq!(list.len(), 1);
176 }
177
178 #[test]
179 fn works_n() {
180 let list = Array::new::<28>().push(1).push("two").push(3.0);
181
182 assert_eq!(list.forward().next().next().value(), &3.0);
183 assert_eq!(list.backward().prev().prev().value(), &1);
184
185 assert_eq!(list.forward().next().index(), 4);
186 assert_eq!(list.backward().index(), 4 + 4 * 4); assert_eq!(list.len(), 3);
189 }
190
191 #[test]
192 fn test_macro() {
193 let list = array![1, "two", 3.0, true];
194
195 let test = list.forward().next().next().prev().next().next();
196 assert_eq!(28, test.index());
197 assert_eq!(&true, test.value());
198 }
199}