stdlib_rs/collections/
second.rs

1use std::mem;
2
3pub struct List {
4    head: Link,
5}
6
7enum Link {
8    Empty,
9    More(Box<Node>),
10}
11
12struct Node {
13    elem: i32,
14    next: Link,
15}
16
17impl Default for List {
18    fn default() -> Self {
19        Self::new()
20    }
21}
22
23impl List {
24    pub fn new() -> Self {
25        List { head: Link::Empty }
26    }
27
28    pub fn push(&mut self, elem: i32) {
29        let new_node = Box::new(Node {
30            elem,
31            next: mem::replace(&mut self.head, Link::Empty),
32        });
33        self.head = Link::More(new_node);
34    }
35
36    pub fn pop(&mut self) -> Option<i32> {
37        match mem::replace(&mut self.head, Link::Empty) {
38            Link::Empty => None,
39            Link::More(node) => {
40                self.head = node.next;
41                Some(node.elem)
42            }
43        }
44    }
45}
46
47impl Drop for List {
48    fn drop(&mut self) {
49        let mut cur_link = mem::replace(&mut self.head, Link::Empty);
50        while let Link::More(mut boxed_node) = cur_link {
51            cur_link = mem::replace(&mut boxed_node.next, Link::Empty);
52        }
53    }
54}
55
56#[cfg(test)]
57mod test {
58    use super::List;
59
60    #[test]
61    fn basics() {
62        let mut list = List::new();
63
64        // Check empty list behaves right
65        assert_eq!(list.pop(), None);
66
67        // Populate list
68        list.push(1);
69        list.push(2);
70        list.push(3);
71
72        // Check normal removal
73        assert_eq!(list.pop(), Some(3));
74        assert_eq!(list.pop(), Some(2));
75
76        // Push some more just to make sure nothing's corrupted
77        list.push(4);
78        list.push(5);
79
80        // Check normal removal
81        assert_eq!(list.pop(), Some(5));
82        assert_eq!(list.pop(), Some(4));
83
84        // Check exhaustion
85        assert_eq!(list.pop(), Some(1));
86        assert_eq!(list.pop(), None);
87    }
88}