1use crate::{Empty, Length};
2use std::mem::forget;
3use traits::*;
4
5pub(crate) mod traits;
6
7pub struct Node<V, N = Empty> {
8 value: *const V,
9 next: N,
10}
11
12impl Node<Empty, Empty> {
13 #[inline]
14 const fn new<V>(value: *const V) -> Node<V> {
15 Node { value, next: Empty }
16 }
17}
18
19impl<V, N> Node<V, N> {
20 #[inline]
21 const fn prepend<V2>(self, value: *const V2) -> Node<V2, Self> {
22 Node { value, next: self }
23 }
24 #[inline]
25 pub const fn value(&self) -> &V {
26 unsafe { &*self.value }
29 }
30
31 #[inline]
32 pub fn value_mut(&mut self) -> &mut V {
33 unsafe { self.value.cast_mut().as_mut().unwrap_unchecked() }
36 }
37
38 #[inline]
39 pub const fn next(&self) -> &N {
40 &self.next
41 }
42
43 #[inline]
44 pub fn next_mut(&mut self) -> &mut N {
45 &mut self.next
46 }
47}
48
49pub struct DynamicList<F, B: DropValue> {
50 forward: F,
51 backward: B,
52}
53
54impl DynamicList<Empty, Empty> {
55 #[inline]
56 pub const fn new() -> Self {
57 Self {
58 forward: Empty,
59 backward: Empty,
60 }
61 }
62
63 #[inline]
64 pub fn push<V>(self, value: V) -> DynamicList<Node<V>, Node<V>> {
65 let value = Box::into_raw(Box::new(value));
66
67 DynamicList {
68 forward: Node::new(value),
69 backward: Node::new(value),
70 }
71 }
72}
73
74impl Default for DynamicList<Empty, Empty> {
75 fn default() -> Self {
76 Self::new()
77 }
78}
79
80impl<F, N: Length + DropValue> DynamicList<F, N> {
82 #[inline]
83 pub const fn forward(&self) -> &F {
84 &self.forward
85 }
86
87 #[inline]
88 pub fn forward_mut(&mut self) -> &mut F {
89 &mut self.forward
90 }
91
92 #[inline]
93 pub const fn backward(&self) -> &N {
94 &self.backward
95 }
96
97 #[inline]
98 pub fn backward_mut(&mut self) -> &mut N {
99 &mut self.backward
100 }
101
102 #[inline]
103 pub const fn len(&self) -> usize {
104 N::SIZE
105 }
106
107 #[inline]
108 pub const fn is_empty(&self) -> bool {
109 N::SIZE == 0
110 }
111}
112
113impl<F: ListAppend, BV, BN: DropValue> DynamicList<F, Node<BV, BN>> {
115 #[inline]
116 pub fn push<V>(self, value: V) -> DynamicList<F::Output<V>, Node<V, Node<BV, BN>>>
117 where
118 <F as ListAppend>::Output<V>: DropValue,
119 {
120 let value = Box::into_raw(Box::new(value));
121
122 let forward = unsafe { (&self.forward as *const F).read() };
125 let backward = unsafe { (&self.backward as *const Node<BV, BN>).read() };
126 forget(self);
127
128 DynamicList {
129 forward: forward.append(value),
130 backward: backward.prepend(value),
131 }
132 }
133}
134
135impl<F, N: DropValue> Drop for DynamicList<F, N> {
136 fn drop(&mut self) {
137 unsafe {
140 self.backward.drop_values();
141 }
142 }
143}
144
145#[macro_export]
146macro_rules! list {
147 () => {
148 DynamicList::new()
149 };
150 ($($x:expr),+ $(,)?) => {
151 DynamicList::new()$(.push($x))+
152 };
153}
154
155#[cfg(test)]
156mod tests {
157 use super::*;
158 use crate::*;
159 use typenum::*;
160
161 #[test]
162 fn works_1() {
163 let list = DynamicList::new().push(1);
164
165 assert_eq!(list.forward.value(), &1);
166 assert_eq!(list.backward.value(), &1);
167
168 assert_eq!(list.forward.next, Empty);
169 assert_eq!(list.backward.next, Empty);
170
171 assert_eq!(list.len(), 1);
172 }
173
174 #[test]
175 fn works_n() {
176 let list = DynamicList::new().push(1).push("two").push(3.0);
177
178 assert_eq!(list.forward.next.next.value(), &3.0);
179 assert_eq!(list.backward.next.next.value(), &1);
180
181 assert_eq!(list.len(), 3);
182 }
183
184 #[test]
185 fn test_macro() {
186 let list_1 = list![1, "two", 3.0, true];
187 let list_2 = list!().push(1).push("two").push(3.0).push(true);
188
189 assert_eq!(list_1.len(), 4);
190 assert_eq!(list_2.len(), 4);
191 }
192
193 #[test]
194 fn test_drop() {
195 static mut N_DROPS: u8 = 0;
196
197 fn drops() -> u8 {
198 unsafe { N_DROPS }
199 }
200
201 struct Test;
202
203 impl Drop for Test {
204 fn drop(&mut self) {
205 unsafe {
206 N_DROPS += 1;
207 }
208 }
209 }
210
211 drop(Test);
213 assert_eq!(drops(), 1);
214
215 let list = list![Test, Test, Test];
216 drop(list);
217 assert_eq!(drops(), 4);
218 }
219
220 #[test]
221 fn test_index() {
222 let list_1 = list![1, "two", 3.0, true];
223
224 assert_eq!(&1, Index::<U0>::index(list_1.forward()));
225 assert_eq!(&"two", Index::<U1>::index(list_1.forward()));
226 assert_eq!(&3.0, Index::<U2>::index(list_1.forward()));
227 assert_eq!(&true, Index::<U3>::index(list_1.forward()));
228 assert_eq!(Empty, Index::<U4>::index(list_1.forward()));
229
230 assert_eq!(Empty, Index::<U100>::index(list_1.forward()));
231 }
232}