Skip to main content

ferroui_base/utilities/
single_or_queue.rs

1use std::collections::VecDeque;
2
3/// FIFO Queue optimized for holding zero or one items.
4pub struct SingleOrQueue<T> {
5    head: Option<T>,
6    tail: Option<VecDeque<T>>,
7    empty: bool,
8}
9
10impl<T> Default for SingleOrQueue<T> {
11    fn default() -> Self {
12        Self::new()
13    }
14}
15
16impl<T> SingleOrQueue<T> {
17    pub fn new() -> Self {
18        Self { head: None, tail: None, empty: true }
19    }
20
21    fn tail(&mut self) -> &mut VecDeque<T> {
22        self.tail.get_or_insert_with(VecDeque::new)
23    }
24
25    fn has_tail(&self) -> bool {
26        self.tail.is_some()
27    }
28
29    pub fn empty(&self) -> bool {
30        self.empty
31    }
32
33    pub fn enqueue(&mut self, value: T) {
34        if self.empty {
35            self.head = Some(value);
36        } else {
37            self.tail().push_back(value);
38        }
39
40        self.empty = false;
41    }
42
43    /// Panics when the queue is empty.
44    pub fn dequeue(&mut self) -> T {
45        if self.empty {
46            panic!("Cannot dequeue from an empty queue!");
47        }
48
49        let result = self.head.take();
50
51        if self.has_tail() && !self.tail().is_empty() {
52            self.head = self.tail().pop_front();
53        } else {
54            self.head = None;
55            self.empty = true;
56        }
57
58        match result {
59            Some(result) => result,
60            None => unreachable!("a queue that is not empty has a head"),
61        }
62    }
63}
64
65#[cfg(test)]
66mod tests {
67    use super::*;
68
69    #[test]
70    fn new_single_or_queue_is_empty() {
71        assert!(SingleOrQueue::<String>::new().empty());
72    }
73
74    #[test]
75    #[should_panic(expected = "Cannot dequeue from an empty queue!")]
76    fn dequeue_throws_when_empty() {
77        let mut queue = SingleOrQueue::<String>::new();
78
79        queue.dequeue();
80    }
81
82    #[test]
83    fn enqueue_adds_element() {
84        let mut queue = SingleOrQueue::<i32>::new();
85
86        queue.enqueue(1);
87
88        assert!(!queue.empty());
89
90        assert_eq!(1, queue.dequeue());
91    }
92
93    #[test]
94    fn multiple_elements_dequeued_in_correct_order() {
95        let mut queue = SingleOrQueue::<i32>::new();
96
97        queue.enqueue(1);
98        queue.enqueue(2);
99        queue.enqueue(3);
100        assert_eq!(1, queue.dequeue());
101        assert_eq!(2, queue.dequeue());
102        assert_eq!(3, queue.dequeue());
103    }
104}