Algod/data_structures/
linked_list.rs

1use std::fmt::{self, Display, Formatter};
2use std::marker::PhantomData;
3use std::ptr::NonNull;
4
5struct Node<T> {
6    val: T,
7    next: Option<NonNull<Node<T>>>,
8    prev: Option<NonNull<Node<T>>>,
9}
10
11impl<T> Node<T> {
12    fn new(t: T) -> Node<T> {
13        Node {
14            val: t,
15            prev: None,
16            next: None,
17        }
18    }
19}
20
21pub struct LinkedList<T> {
22    length: u32,
23    head: Option<NonNull<Node<T>>>,
24    tail: Option<NonNull<Node<T>>>,
25    // Act like we own boxed nodes since we construct and leak them
26    marker: PhantomData<Box<Node<T>>>,
27}
28
29impl<T> Default for LinkedList<T> {
30    fn default() -> Self {
31        Self::new()
32    }
33}
34
35impl<T> LinkedList<T> {
36    pub fn new() -> Self {
37        Self {
38            length: 0,
39            head: None,
40            tail: None,
41            marker: PhantomData,
42        }
43    }
44
45    pub fn insert_at_head(&mut self, obj: T) {
46        let mut node = Box::new(Node::new(obj));
47        node.next = self.head;
48        node.prev = None;
49        let node_ptr = Some(unsafe { NonNull::new_unchecked(Box::into_raw(node)) });
50        match self.head {
51            None => self.tail = node_ptr,
52            Some(head_ptr) => unsafe { (*head_ptr.as_ptr()).prev = node_ptr },
53        }
54        self.head = node_ptr;
55        self.length += 1;
56    }
57
58    pub fn insert_at_tail(&mut self, obj: T) {
59        let mut node = Box::new(Node::new(obj));
60        node.next = None;
61        node.prev = self.tail;
62        let node_ptr = Some(unsafe { NonNull::new_unchecked(Box::into_raw(node)) });
63        match self.tail {
64            None => self.head = node_ptr,
65            Some(tail_ptr) => unsafe { (*tail_ptr.as_ptr()).next = node_ptr },
66        }
67        self.tail = node_ptr;
68        self.length += 1;
69    }
70
71    pub fn insert_at_ith(&mut self, index: u32, obj: T) {
72        if self.length < index {
73            panic!("Index out of bounds");
74        }
75
76        if index == 0 || self.head == None {
77            self.insert_at_head(obj);
78            return;
79        }
80
81        if self.length == index {
82            self.insert_at_tail(obj);
83            return;
84        }
85
86        if let Some(mut ith_node) = self.head {
87            for _ in 0..index {
88                unsafe {
89                    match (*ith_node.as_ptr()).next {
90                        None => panic!("Index out of bounds"),
91                        Some(next_ptr) => ith_node = next_ptr,
92                    }
93                }
94            }
95
96            let mut node = Box::new(Node::new(obj));
97            unsafe {
98                node.prev = (*ith_node.as_ptr()).prev;
99                node.next = Some(ith_node);
100                if let Some(p) = (*ith_node.as_ptr()).prev {
101                    let node_ptr = Some(NonNull::new_unchecked(Box::into_raw(node)));
102                    println!("{:?}", (*p.as_ptr()).next);
103                    (*p.as_ptr()).next = node_ptr;
104                    self.length += 1;
105                }
106            }
107        }
108    }
109
110    pub fn delete_head(&mut self) -> Option<T> {
111        // Safety: head_ptr points to a leaked boxed node managed by this list
112        // We reassign pointers that pointed to the head node
113        self.head.map(|head_ptr| unsafe {
114            let old_head = Box::from_raw(head_ptr.as_ptr());
115            match old_head.next {
116                Some(mut next_ptr) => next_ptr.as_mut().prev = None,
117                None => self.tail = None,
118            }
119            self.head = old_head.next;
120            self.length -= 1;
121            old_head.val
122        })
123    }
124
125    pub fn delete_tail(&mut self) -> Option<T> {
126        // Safety: tail_ptr points to a leaked boxed node managed by this list
127        // We reassign pointers that pointed to the tail node
128        self.tail.map(|tail_ptr| unsafe {
129            let old_tail = Box::from_raw(tail_ptr.as_ptr());
130            match old_tail.prev {
131                Some(mut prev) => prev.as_mut().next = None,
132                None => self.head = None,
133            }
134            self.tail = old_tail.prev;
135            self.length -= 1;
136            old_tail.val
137        })
138    }
139
140    pub fn delete_ith(&mut self, index: u32) -> Option<T> {
141        if self.length < index {
142            panic!("Index out of bounds");
143        }
144
145        if index == 0 || self.head == None {
146            return self.delete_head();
147        }
148
149        if self.length == index {
150            return self.delete_tail();
151        }
152
153        if let Some(mut ith_node) = self.head {
154            for _ in 0..index {
155                unsafe {
156                    match (*ith_node.as_ptr()).next {
157                        None => panic!("Index out of bounds"),
158                        Some(next_ptr) => ith_node = next_ptr,
159                    }
160                }
161            }
162
163            unsafe {
164                let old_ith = Box::from_raw(ith_node.as_ptr());
165                if let Some(mut prev) = old_ith.prev {
166                    prev.as_mut().next = old_ith.next;
167                }
168                if let Some(mut next) = old_ith.next {
169                    next.as_mut().prev = old_ith.prev;
170                }
171
172                self.length -= 1;
173                Some(old_ith.val)
174            }
175        } else {
176            None
177        }
178    }
179
180    pub fn get(&mut self, index: i32) -> Option<&T> {
181        self.get_ith_node(self.head, index)
182    }
183
184    fn get_ith_node(&mut self, node: Option<NonNull<Node<T>>>, index: i32) -> Option<&T> {
185        match node {
186            None => None,
187            Some(next_ptr) => match index {
188                0 => Some(unsafe { &(*next_ptr.as_ptr()).val }),
189                _ => self.get_ith_node(unsafe { (*next_ptr.as_ptr()).next }, index - 1),
190            },
191        }
192    }
193}
194
195impl<T> Drop for LinkedList<T> {
196    fn drop(&mut self) {
197        // Pop items until there are none left
198        while self.delete_head().is_some() {}
199    }
200}
201
202impl<T> Display for LinkedList<T>
203where
204    T: Display,
205{
206    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
207        match self.head {
208            Some(node) => write!(f, "{}", unsafe { node.as_ref() }),
209            None => Ok(()),
210        }
211    }
212}
213
214impl<T> Display for Node<T>
215where
216    T: Display,
217{
218    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
219        match self.next {
220            Some(node) => write!(f, "{}, {}", self.val, unsafe { node.as_ref() }),
221            None => write!(f, "{}", self.val),
222        }
223    }
224}
225
226#[cfg(test)]
227mod tests {
228    use std::convert::TryInto;
229
230    use super::LinkedList;
231
232    #[test]
233    fn insert_at_tail_works() {
234        let mut list = LinkedList::<i32>::new();
235        let second_value = 2;
236        list.insert_at_tail(1);
237        list.insert_at_tail(second_value);
238        println!("Linked List is {}", list);
239        match list.get(1) {
240            Some(val) => assert_eq!(*val, second_value),
241            None => panic!("Expected to find {} at index 1", second_value),
242        }
243    }
244    #[test]
245    fn insert_at_head_works() {
246        let mut list = LinkedList::<i32>::new();
247        let second_value = 2;
248        list.insert_at_head(1);
249        list.insert_at_head(second_value);
250        println!("Linked List is {}", list);
251        match list.get(0) {
252            Some(val) => assert_eq!(*val, second_value),
253            None => panic!("Expected to find {} at index 0", second_value),
254        }
255    }
256
257    #[test]
258    fn insert_at_ith_can_add_to_tail() {
259        let mut list = LinkedList::<i32>::new();
260        let second_value = 2;
261        list.insert_at_ith(0, 0);
262        list.insert_at_ith(1, second_value);
263        println!("Linked List is {}", list);
264        match list.get(1) {
265            Some(val) => assert_eq!(*val, second_value),
266            None => panic!("Expected to find {} at index 1", second_value),
267        }
268    }
269
270    #[test]
271    fn insert_at_ith_can_add_to_head() {
272        let mut list = LinkedList::<i32>::new();
273        let second_value = 2;
274        list.insert_at_ith(0, 1);
275        list.insert_at_ith(0, second_value);
276        println!("Linked List is {}", list);
277        match list.get(0) {
278            Some(val) => assert_eq!(*val, second_value),
279            None => panic!("Expected to find {} at index 0", second_value),
280        }
281    }
282
283    #[test]
284    fn insert_at_ith_can_add_to_middle() {
285        let mut list = LinkedList::<i32>::new();
286        let second_value = 2;
287        let third_value = 3;
288        list.insert_at_ith(0, 1);
289        list.insert_at_ith(1, second_value);
290        list.insert_at_ith(1, third_value);
291        println!("Linked List is {}", list);
292        match list.get(1) {
293            Some(val) => assert_eq!(*val, third_value),
294            None => panic!("Expected to find {} at index 1", third_value),
295        }
296
297        match list.get(2) {
298            Some(val) => assert_eq!(*val, second_value),
299            None => panic!("Expected to find {} at index 1", second_value),
300        }
301    }
302
303    #[test]
304    fn insert_at_ith_and_delete_ith_work_over_many_iterations() {
305        let mut list = LinkedList::<i32>::new();
306        for i in 0..100 {
307            list.insert_at_ith(i, i.try_into().unwrap());
308        }
309
310        // Pop even numbers to 50
311        for i in 0..50 {
312            println!("list.length {}", list.length);
313            if i % 2 == 0 {
314                list.delete_ith(i);
315            }
316        }
317
318        assert_eq!(list.length, 75);
319
320        // Insert even numbers back
321        for i in 0..50 {
322            if i % 2 == 0 {
323                list.insert_at_ith(i, i.try_into().unwrap());
324            }
325        }
326
327        assert_eq!(list.length, 100);
328
329        // Ensure numbers were adderd back and we're able to traverse nodes
330        if let Some(val) = list.get(78) {
331            assert_eq!(*val, 78);
332        } else {
333            panic!("Expected to find 78 at index 78");
334        }
335    }
336
337    #[test]
338    fn delete_tail_works() {
339        let mut list = LinkedList::<i32>::new();
340        let first_value = 1;
341        let second_value = 2;
342        list.insert_at_tail(first_value);
343        list.insert_at_tail(second_value);
344        match list.delete_tail() {
345            Some(val) => assert_eq!(val, 2),
346            None => panic!("Expected to remove {} at tail", second_value),
347        }
348
349        println!("Linked List is {}", list);
350        match list.get(0) {
351            Some(val) => assert_eq!(*val, first_value),
352            None => panic!("Expected to find {} at index 0", first_value),
353        }
354    }
355
356    #[test]
357    fn delete_head_works() {
358        let mut list = LinkedList::<i32>::new();
359        let first_value = 1;
360        let second_value = 2;
361        list.insert_at_tail(first_value);
362        list.insert_at_tail(second_value);
363        match list.delete_head() {
364            Some(val) => assert_eq!(val, 1),
365            None => panic!("Expected to remove {} at head", first_value),
366        }
367
368        println!("Linked List is {}", list);
369        match list.get(0) {
370            Some(val) => assert_eq!(*val, second_value),
371            None => panic!("Expected to find {} at index 0", second_value),
372        }
373    }
374
375    #[test]
376    fn delete_ith_can_delete_at_tail() {
377        let mut list = LinkedList::<i32>::new();
378        let first_value = 1;
379        let second_value = 2;
380        list.insert_at_tail(first_value);
381        list.insert_at_tail(second_value);
382        match list.delete_ith(1) {
383            Some(val) => assert_eq!(val, 2),
384            None => panic!("Expected to remove {} at tail", second_value),
385        }
386
387        assert_eq!(list.length, 1);
388    }
389
390    #[test]
391    fn delete_ith_can_delete_at_head() {
392        let mut list = LinkedList::<i32>::new();
393        let first_value = 1;
394        let second_value = 2;
395        list.insert_at_tail(first_value);
396        list.insert_at_tail(second_value);
397        match list.delete_ith(0) {
398            Some(val) => assert_eq!(val, 1),
399            None => panic!("Expected to remove {} at tail", first_value),
400        }
401
402        assert_eq!(list.length, 1);
403    }
404
405    #[test]
406    fn delete_ith_can_delete_in_middle() {
407        let mut list = LinkedList::<i32>::new();
408        let first_value = 1;
409        let second_value = 2;
410        let third_value = 3;
411        list.insert_at_tail(first_value);
412        list.insert_at_tail(second_value);
413        list.insert_at_tail(third_value);
414        match list.delete_ith(1) {
415            Some(val) => assert_eq!(val, 2),
416            None => panic!("Expected to remove {} at tail", second_value),
417        }
418
419        match list.get(1) {
420            Some(val) => assert_eq!(*val, third_value),
421            None => panic!("Expected to find {} at index 1", third_value),
422        }
423    }
424
425    #[test]
426    fn create_numeric_list() {
427        let mut list = LinkedList::<i32>::new();
428        list.insert_at_tail(1);
429        list.insert_at_tail(2);
430        list.insert_at_tail(3);
431        println!("Linked List is {}", list);
432        assert_eq!(3, list.length);
433    }
434
435    #[test]
436    fn create_string_list() {
437        let mut list_str = LinkedList::<String>::new();
438        list_str.insert_at_tail("A".to_string());
439        list_str.insert_at_tail("B".to_string());
440        list_str.insert_at_tail("C".to_string());
441        println!("Linked List is {}", list_str);
442        assert_eq!(3, list_str.length);
443    }
444
445    #[test]
446    fn get_by_index_in_numeric_list() {
447        let mut list = LinkedList::<i32>::new();
448        list.insert_at_tail(1);
449        list.insert_at_tail(2);
450        println!("Linked List is {}", list);
451        let retrived_item = list.get(1);
452        assert!(retrived_item.is_some());
453        assert_eq!(2 as i32, *retrived_item.unwrap());
454    }
455
456    #[test]
457    fn get_by_index_in_string_list() {
458        let mut list_str = LinkedList::<String>::new();
459        list_str.insert_at_tail("A".to_string());
460        list_str.insert_at_tail("B".to_string());
461        println!("Linked List is {}", list_str);
462        let retrived_item = list_str.get(1);
463        assert!(retrived_item.is_some());
464        assert_eq!("B", *retrived_item.unwrap());
465    }
466}