1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use std::collections::VecDeque;

/// A dynamic deque that can store elements in a stack or a heap.
/// First, elements are pushed to the stack. If the stack is full, elements are pushed to the heap.
/// When popping elements, the stack is popped first. If the stack is empty and the heap is not, the
/// heap is popped and the elements are pushed to the stack.
/// Example:
/// ```
/// use sans_io_runtime::collections::DynamicDeque;
/// let mut deque: DynamicDeque<i32, 5> = DynamicDeque::default();
/// deque.push_back_stack(1).unwrap();
/// deque.push_back_stack(2).unwrap();
/// deque.push_back_stack(3).unwrap();
/// deque.push_back_stack(4).unwrap();
/// deque.push_back_stack(5).unwrap();
/// deque.push_back(6); // Should overflow to heap
/// assert_eq!(deque.len(), 6);
/// ```
#[derive(Debug)]
pub struct DynamicDeque<T, const STACK_SIZE: usize> {
    stack: heapless::Deque<T, STACK_SIZE>,
    heap: VecDeque<T>,
}

impl<T, const STACK_SIZE: usize> Default for DynamicDeque<T, STACK_SIZE> {
    fn default() -> Self {
        Self {
            stack: heapless::Deque::new(),
            heap: VecDeque::new(),
        }
    }
}

#[allow(unused)]
impl<T, const STATIC_SIZE: usize> DynamicDeque<T, STATIC_SIZE> {
    /// Creates a new instance of `DynamicDeque` from an array of elements.
    ///
    /// # Arguments
    ///
    /// * `prepare` - An array of elements to initialize the deque with.
    ///
    /// # Returns
    ///
    /// A new instance of `DynamicDeque`.
    pub fn from<const SIZE: usize>(prepare: [T; SIZE]) -> Self {
        let mut instance = Self::default();
        for item in prepare {
            instance.push_back(item);
        }
        instance
    }

    /// Pushes an element to the stack of the deque.
    ///
    /// # Arguments
    ///
    /// * `value` - The value to be pushed.
    ///
    /// # Returns
    ///
    /// * `Ok(())` - If the element was successfully pushed.
    /// * `Err(value)` - If the element could not be pushed due to overflow.
    pub fn push_back_stack(&mut self, value: T) -> Result<(), T> {
        self.stack.push_back(value)
    }

    /// Pushes an element to the stack or the heap of the deque.
    ///
    /// # Arguments
    ///
    /// * `value` - The value to be pushed.
    pub fn push_back(&mut self, value: T) {
        if let Err(value) = self.stack.push_back(value) {
            self.heap.push_back(value);
        }
    }

    /// Pops the element from the front of the deque.
    ///
    /// # Returns
    ///
    /// The popped element, or `None` if the deque is empty.
    pub fn pop_front(&mut self) -> Option<T> {
        let res = self.stack.pop_front();
        if !self.stack.is_full() && !self.heap.is_empty() {
            let front = self.heap.pop_front().expect("Should have");
            if self.stack.push_back(front).is_err() {
                panic!("cannot happen");
            }
        }
        res
    }

    /// Checks if the deque is empty.
    ///
    /// # Returns
    ///
    /// `true` if the deque is empty, `false` otherwise.
    pub fn is_empty(&self) -> bool {
        self.stack.is_empty()
    }

    /// Returns the number of elements in the deque.
    ///
    /// # Returns
    ///
    /// The number of elements in the deque.
    pub fn len(&self) -> usize {
        self.stack.len() + self.heap.len()
    }

    /// This is useful in task where we usually doing output in queue
    /// We need push to back then immediate pop from front
    #[inline(always)]
    pub fn pop2(&mut self, e: T) -> T {
        if self.is_empty() {
            e
        } else {
            let out = self.pop_front().expect("Should have because just push");
            self.push_back(e);
            out
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_push_back() {
        let mut deque: DynamicDeque<i32, 2> = DynamicDeque::default();
        assert!(deque.push_back_stack(1).is_ok());
        assert!(deque.push_back_stack(2).is_ok());
        assert!(deque.push_back_stack(3).is_err());
        assert_eq!(deque.len(), 2);
        deque.push_back(3);
        assert_eq!(deque.len(), 3);
    }

    #[test]
    fn test_pop_front() {
        let mut deque: DynamicDeque<i32, 2> = DynamicDeque::default();
        deque.push_back(1);
        deque.push_back(2);
        deque.push_back(3);
        assert_eq!(deque.pop_front(), Some(1));
        assert_eq!(deque.pop_front(), Some(2));
        assert_eq!(deque.pop_front(), Some(3));
        assert_eq!(deque.pop_front(), None);
        assert_eq!(deque.len(), 0);
    }

    #[test]
    fn test_is_empty() {
        let mut deque: DynamicDeque<i32, 2> = DynamicDeque::default();
        assert_eq!(deque.is_empty(), true);
        deque.push_back(1);
        assert_eq!(deque.is_empty(), false);
        deque.pop_front();
        assert_eq!(deque.is_empty(), true);
    }
}