1use std::ptr::NonNull;
2
3#[derive(Debug)]
4pub struct DoublyLinkedList<T> {
5 head: Option<NonNull<Node<T>>>,
6 tail: Option<NonNull<Node<T>>>,
7 elements: usize,
8}
9
10#[derive(Debug)]
11pub struct Node<T> {
12 pub elem: T,
13 pub next: Option<NonNull<Node<T>>>,
14 pub prev: Option<NonNull<Node<T>>>,
15}
16
17#[cfg(feature = "matecito")]
19unsafe impl<T> Send for DoublyLinkedList<T> {}
20#[cfg(feature = "matecito")]
21unsafe impl<T> Sync for DoublyLinkedList<T> {}
22
23impl<T> DoublyLinkedList<T> {
24 pub fn new() -> Self {
25 Self {
26 head: None,
27 tail: None,
28 elements: 0,
29 }
30 }
31
32 pub fn delete(&mut self, non_null_node: NonNull<Node<T>>) -> Option<T> {
33 let mut non_null_node = non_null_node; let node = unsafe { non_null_node.as_mut() };
35
36 let prev_node = match node.prev {
37 None => None,
38 Some(mut pnode) => NonNull::new(unsafe { pnode.as_mut() }),
39 };
40
41 let next_node = match node.next {
42 None => None,
43 Some(mut pnode) => NonNull::new(unsafe { pnode.as_mut() }),
44 };
45
46 match next_node {
47 None => {
50 self.tail = prev_node;
51 }
52 Some(mut nnode_opt) => {
53 let next_node = unsafe { nnode_opt.as_mut() };
54 next_node.prev = prev_node;
55 }
56 }
57
58 match prev_node {
59 None => {
62 self.head = next_node;
63 }
64 Some(nnode_opt) => {
65 let prev_node = unsafe { nnode_opt.as_ptr().as_mut().unwrap() };
66 prev_node.next = next_node;
67 }
68 }
69
70 let node = unsafe { Box::from_raw(node) };
72
73 self.elements -= 1;
74 Some(node.elem)
75 }
76
77 pub fn push_back(&mut self, elem: T) -> NonNull<Node<T>> {
78 let node = Node {
85 elem,
86 next: None,
87 prev: None,
88 };
89 let boxed_node = Box::into_raw(Box::new(node));
90 let node = NonNull::new(boxed_node);
91
92 let raw_old_head = self.head;
93
94 if self.head.is_none() {
96 self.head = node;
97 self.tail = node;
98 self.elements += 1;
99 return self.head.unwrap();
100 }
101
102 self.head = node;
104
105 match raw_old_head {
106 None => (),
107 Some(mut non_null_node) => unsafe {
108 non_null_node.as_mut().prev = node;
109 self.head.unwrap().as_mut().next = raw_old_head;
110 },
111 };
112 self.elements += 1;
113 return self.head.unwrap();
114 }
115
116 pub fn pop_front(&mut self) -> Option<T> {
117 if self.tail.is_none() {
119 return None;
120 }
121 let old_tail = self.tail;
124
125 self.tail = match old_tail {
126 None => return None,
127 Some(mut non_null_node) => unsafe { non_null_node.as_mut().prev },
128 };
129
130 if self.tail.is_none() {
131 self.head = None;
132 }
133
134 let old_tail = unsafe { Box::from_raw(old_tail.unwrap().as_ptr()) };
135 self.elements -= 1;
136 Some(old_tail.elem)
137 }
138
139 #[allow(dead_code)]
140 pub fn pop_back(&mut self) -> Option<T> {
141 if self.head.is_none() {
143 return None;
144 }
145 let old_head = self.head;
148
149 self.head = match old_head {
150 None => return None,
151 Some(mut non_null_node) => unsafe { non_null_node.as_mut().next },
152 };
153
154 if self.head.is_none() {
155 self.tail = None;
156 }
157
158 let result = unsafe { Box::from_raw(old_head.unwrap().as_ptr()) };
159 self.elements -= 1;
160 Some(result.elem)
161 }
162
163 #[allow(dead_code)]
164 pub fn peek_front(&self) -> Option<&NonNull<Node<T>>> {
165 if self.tail.is_none() {
166 return None;
167 }
168 self.tail.as_ref()
169 }
170
171 pub fn is_empty(&self) -> bool {
172 self.elements == 0
173 }
174
175 pub fn num_elements(&self) -> usize {
176 self.elements
177 }
178}
179
180impl<T> Drop for DoublyLinkedList<T> {
181 fn drop(&mut self) {
182 while !self.is_empty() {
183 self.pop_front();
184 }
185 }
186}
187#[cfg(test)]
188mod tests {
189 use super::*;
190
191 #[test]
192 fn push_front_and_pop_front() {
193 let mut dll = DoublyLinkedList::new();
194 assert_eq!(None, dll.pop_front());
195 let range = std::ops::Range {
196 start: 10,
197 end: 100,
198 };
199
200 for num in 0..range.len() {
201 dll.push_back(num);
202 }
203
204 for num in 0..range.len() {
205 assert_eq!(Some(num), dll.pop_front());
206 }
207 assert_eq!(None, dll.pop_front());
208 }
209
210 #[test]
211 fn push_front_and_pop_back() {
212 let mut dll = DoublyLinkedList::new();
213 assert_eq!(None, dll.pop_back());
214 let range = std::ops::Range {
215 start: 10,
216 end: 100,
217 };
218 for num in range.clone() {
219 dll.push_back(num);
220 }
221
222 for num in range.clone().rev().clone() {
223 assert_eq!(Some(num), dll.pop_back());
224 }
225 assert_eq!(None, dll.pop_back());
226 }
227
228 #[test]
229 fn populate_and_delete() {
230 let mut dll = DoublyLinkedList::new();
231 let range = std::ops::Range { start: 0, end: 3 };
232
233 let mut elements = vec![];
234 for num in range.clone() {
235 let node = dll.push_back(num as i32);
236 elements.push(node);
237 }
238
239 dll.delete(elements[1]);
240 dll.delete(elements[0]);
241 assert_eq!(Some(2), dll.pop_front());
242 assert!(dll.is_empty());
243 assert_eq!(None, dll.pop_front());
244 }
245
246 #[test]
247 fn num_elements() {
248 let mut dll = DoublyLinkedList::new();
249 let range = std::ops::Range { start: 0, end: 3 };
250
251 let mut num_elements = range.len();
253 let mut elements = vec![];
254 for num in range.clone() {
255 let node = dll.push_back(num as i32);
256 elements.push(node);
257 }
258 for num in range.clone() {
259 dll.delete(elements[num]);
260 num_elements -= 1;
261 assert_eq!(num_elements, dll.num_elements());
262 }
263
264 let mut num_elements = range.len();
266 for num in range.clone() {
267 dll.push_back(num as i32);
268 }
269 for _ in range.clone() {
270 dll.pop_front();
271 num_elements -= 1;
272 assert_eq!(num_elements, dll.num_elements());
273 }
274
275 let mut num_elements = range.len();
277 for num in range.clone() {
278 dll.push_back(num as i32);
279 }
280 for _ in range.clone() {
281 dll.pop_back();
282 num_elements -= 1;
283 assert_eq!(num_elements, dll.num_elements());
284 }
285 }
286
287 #[test]
288 fn edge_case_push_after_emptied_delete_and_empty_again() {
289 let mut dll = DoublyLinkedList::new();
290 let n1 = dll.push_back(1);
291 let n2 = dll.push_back(2);
292 let n3 = dll.push_back(3);
293
294 dll.delete(n1);
295 assert_eq!(2, dll.num_elements());
296
297 dll.delete(n2);
298 assert_eq!(1, dll.num_elements());
299
300 dll.delete(n3);
301 assert_eq!(0, dll.num_elements());
302 assert!(dll.is_empty());
303
304 let n1 = dll.push_back(1);
305 assert_eq!(1, dll.num_elements());
306 dll.delete(n1);
307 assert_eq!(0, dll.num_elements());
308 assert!(dll.is_empty());
309 }
310
311 #[test]
312 fn edge_case_push_after_emptied_pop_front_and_empty_again() {
313 let mut dll = DoublyLinkedList::new();
314 dll.push_back(1);
315 dll.push_back(2);
316 dll.push_back(3);
317
318 dll.pop_front();
319 assert_eq!(2, dll.num_elements());
320
321 dll.pop_front();
322 assert_eq!(1, dll.num_elements());
323
324 dll.pop_front();
325 assert_eq!(0, dll.num_elements());
326 assert!(dll.is_empty());
327
328 dll.push_back(1);
329 assert_eq!(1, dll.num_elements());
330 dll.pop_front();
331 assert_eq!(0, dll.num_elements());
332 assert!(dll.is_empty());
333 }
334
335 #[test]
336 fn edge_case_push_after_emptied_pop_back_and_empty_again() {
337 let mut dll = DoublyLinkedList::new();
338 dll.push_back(1);
339 dll.push_back(2);
340 dll.push_back(3);
341
342 dll.pop_back();
343 assert_eq!(2, dll.num_elements());
344
345 dll.pop_back();
346 assert_eq!(1, dll.num_elements());
347
348 dll.pop_back();
349 assert_eq!(0, dll.num_elements());
350 assert!(dll.is_empty());
351
352 dll.push_back(1);
353 assert_eq!(1, dll.num_elements());
354 dll.pop_back();
355 assert_eq!(0, dll.num_elements());
356 assert_eq!(None, dll.pop_back());
357 assert!(dll.is_empty());
358 }
359}