dynamic_list/array/
mod.rs

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
12// ZST
13pub 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], // Array of bytes
21    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        // TODO: ChecK N is doesn't wrap around
42        // TODO: Try to cast transmute self without moving it
43        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            // TODO: Find a way to fix unaligned error
131            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); // 1 32bit + 4 chars
187
188        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}