1use crate::error::Result;
4
5use super::array::Vec;
6use super::boxed::Box;
7
8#[proc_macros::fmt]
10pub struct Queue<T: Clone, const N: usize> {
11 data: Vec<T, N>,
12 len: usize,
13 front: usize,
14}
15
16#[allow(dead_code)]
17impl<T: Clone + Copy, const N: usize> Queue<T, N> {
18 pub const fn new() -> Self {
20 Self {
21 data: Vec::new(),
22 len: 0,
23 front: 0,
24 }
25 }
26
27 pub fn push_back(&mut self, value: T) -> Result<()> {
33 if self.len == self.data.capacity() {
34 return Err(kerr!(ENOMEM));
35 }
36 self.len += 1;
37 if self.data.len() != self.data.capacity() {
38 self.data.push(value)?;
39 } else {
40 self.insert(self.len - 1, value)?;
41 }
42
43 Ok(())
44 }
45
46 pub fn pop_front(&mut self) -> Option<T> {
50 if self.len == 0 {
51 return None;
52 }
53
54 let value = self.data.at(self.front).cloned();
55
56 self.front = (self.front + 1) % self.data.capacity();
57 self.len -= 1;
58 value
59 }
60
61 pub fn insert(&mut self, index: usize, value: T) -> Result<()> {
68 if index >= self.len() {
69 return Err(kerr!(EINVAL));
70 }
71 let real_idx = (self.front + index) % self.data.capacity();
72 self.data
73 .at_mut(real_idx)
74 .map(|insertion_point| *insertion_point = value)
75 .ok_or(kerr!(EINVAL))
76 }
77
78 pub fn front(&self) -> Option<&T> {
80 if self.is_empty() {
81 return None;
82 }
83
84 self.data.at(self.front)
85 }
86
87 pub fn back(&self) -> Option<&T> {
89 if self.is_empty() {
90 return None;
91 }
92 let back = (self.front + self.len - 1) % self.data.capacity();
93 self.data.at(back)
94 }
95
96 pub fn len(&self) -> usize {
98 self.len
99 }
100
101 pub fn is_empty(&self) -> bool {
103 self.len == 0
104 }
105
106 pub fn grow_capacity(&mut self, new_size: usize) -> Result<()> {
113 if new_size <= self.data.capacity() {
114 return Ok(());
115 }
116 if self.front + self.len >= self.data.capacity() {
118 let non_wrapping_queue_start_len = self.data.capacity() - self.front;
123 let mut swap_helper = Box::new_slice_uninit(non_wrapping_queue_start_len)?;
124 bug_on!(swap_helper.len() != non_wrapping_queue_start_len);
125
126 for i in 0..swap_helper.len() {
128 swap_helper[i].write(self.data.at(self.front + i).copied().ok_or(kerr!(EINVAL))?);
130 }
131 let end = (self.front + self.len) % self.data.capacity();
133 for i in 0..end {
135 bug_on!(i + non_wrapping_queue_start_len >= self.data.capacity());
136 self.data.swap(i, i + non_wrapping_queue_start_len);
137 }
138 for i in 0..non_wrapping_queue_start_len {
140 if let Some(el) = self.data.at_mut(i) {
142 *el = unsafe { swap_helper[i].assume_init() };
143 }
144 }
145 self.front = 0;
146 }
147 self.data.reserve_total_capacity(new_size)
148 }
149}
150
151#[cfg(test)]
154mod tests {
155 use hal_api::mem::PhysAddr;
156
157 use super::*;
158 use crate::mem::GLOBAL_ALLOCATOR;
159 use core::ops::Range;
160
161 fn alloc_range(length: usize) -> Range<PhysAddr> {
162 let alloc_range = std::alloc::Layout::from_size_align(length, align_of::<u128>()).unwrap();
163 let ptr = unsafe { std::alloc::alloc(alloc_range) };
164 PhysAddr::new(ptr as usize)..PhysAddr::new(ptr as usize) + length
165 }
166
167 fn setup_memory(mem_size: usize) {
168 unsafe {
169 GLOBAL_ALLOCATOR
170 .lock()
171 .add_range(&alloc_range(mem_size))
172 .unwrap()
173 };
174 }
175
176 #[test]
177 fn growing_retains_queue_state_without_wrapping() {
178 setup_memory(1000);
179 let mut queue = Queue::<usize, 10>::new();
180 for i in 0..10 {
181 assert_eq!(queue.push_back(i), Ok(()));
182 }
183
184 assert_eq!(queue.grow_capacity(20), Ok(()));
185 for i in 0..10 {
186 assert_eq!(queue.pop_front(), Some(i));
187 }
188 }
189
190 #[test]
191 fn growing_retains_queue_state_with_wrapping() {
192 setup_memory(1000);
193 let mut queue = Queue::<usize, 10>::new();
194 for i in 0..10 {
195 assert_eq!(queue.push_back(i), Ok(()));
196 }
197 assert_eq!(queue.push_back(1), Err(kerr!(ENOMEM)));
199 assert_eq!(queue.len(), 10);
200
201 for i in 0..5 {
203 assert_eq!(queue.pop_front(), Some(i));
204 }
205
206 assert_eq!(*queue.front().unwrap(), 5);
207 assert_eq!(*queue.back().unwrap(), 9);
208 assert_eq!(queue.len(), 5);
209
210 for i in 10..15 {
211 assert_eq!(queue.push_back(i), Ok(()));
212 }
213
214 assert_eq!(queue.len(), 10);
215 assert_eq!(*queue.front().unwrap(), 5);
216 assert_eq!(*queue.back().unwrap(), 14);
217 assert_eq!(queue.grow_capacity(20), Ok(()));
218 for i in 5..15 {
219 assert_eq!(queue.pop_front(), Some(i));
220 }
221 }
222
223 #[test]
224 fn growing_to_smaller_size_has_no_effect() {
225 setup_memory(1000);
226 let mut queue = Queue::<usize, 10>::new();
227 for i in 0..10 {
228 assert_eq!(queue.push_back(i), Ok(()));
229 }
230 assert_eq!(queue.len(), 10);
231 queue.grow_capacity(1).unwrap();
232 assert_eq!(queue.len(), 10);
233 assert_eq!(queue.push_back(1), Err(kerr!(ENOMEM)));
234 }
235
236 #[test]
237 fn growing_multiple_times_consecutively_retains_state() {
238 setup_memory(10000);
239 let mut queue = Queue::<usize, 10>::new();
240 for i in 0..10 {
241 assert_eq!(queue.push_back(i), Ok(()));
242 }
243 assert_eq!(queue.len(), 10);
244
245 for i in 0..5 {
247 assert_eq!(queue.pop_front(), Some(i));
248 }
249 assert_eq!(queue.len(), 5);
250
251 for i in 10..15 {
252 assert_eq!(queue.push_back(i), Ok(()));
253 }
254
255 assert_eq!(queue.len(), 10);
256 assert_eq!(*queue.front().unwrap(), 5);
257 assert_eq!(*queue.back().unwrap(), 14);
258 assert_eq!(queue.grow_capacity(20), Ok(()));
259 assert_eq!(queue.grow_capacity(40), Ok(()));
260 assert_eq!(queue.grow_capacity(100), Ok(()));
261 assert_eq!(queue.grow_capacity(200), Ok(()));
262 for i in 5..15 {
263 assert_eq!(queue.pop_front(), Some(i));
264 }
265 }
266}
267#[cfg(kani)]
271mod verification {
272 use super::*;
273 use core::cmp::max;
274 use std::cmp::min;
275 use std::vec::Vec;
276
277 #[test]
278 fn kani_concrete_playback_growing_retains_queue_state_with_wrapping_7154119071478699851() {
279 let concrete_vals: Vec<Vec<u8>> = vec![
280 vec![128, 134, 1, 0, 0, 0, 0, 0],
282 ];
283 kani::concrete_playback_run(concrete_vals, growing_retains_queue_state_with_wrapping);
284 }
285
286 fn growing_retains_queue_state_with_wrapping() {
289 let mut queue = Queue::<usize, 10>::new();
290 for i in 0..10 {
291 assert_eq!(queue.push_back(i), Ok(()));
292 }
293 assert_eq!(queue.push_back(1), Err(kerr!(ENOMEM)));
295 assert_eq!(queue.len(), 10);
296
297 for i in 0..5 {
299 assert_eq!(queue.pop_front(), Some(i));
300 }
301
302 assert_eq!(*queue.front().unwrap(), 5);
303 assert_eq!(*queue.back().unwrap(), 9);
304 assert_eq!(queue.len(), 5);
305
306 for i in 10..15 {
307 assert_eq!(queue.push_back(i), Ok(()));
308 }
309
310 assert_eq!(queue.len(), 10);
311 assert_eq!(*queue.front().unwrap(), 5);
312 assert_eq!(*queue.back().unwrap(), 14);
313 let new_cap = kani::any();
314 let res = queue.grow_capacity(new_cap);
315
316 if res == Ok(()) && new_cap > 10 {
317 for i in 0..(new_cap - 10) {
318 assert_eq!(queue.push_back(i), Ok(()));
320 }
321 }
322
323 for i in 5..15 {
324 assert_eq!(queue.pop_front(), Some(i));
325 }
326
327 while !queue.is_empty() {
328 let _ = queue.pop_front();
329 }
330
331 if res == Ok(()) && new_cap > 10 {
333 for i in 0..new_cap {
334 assert_eq!(queue.push_back(i), Ok(()));
335 }
336
337 for i in 0..new_cap {
338 assert_eq!(queue.pop_front(), Some(i));
339 }
340 }
341 }
342}
343