1use std::{
11 marker::PhantomData,
12 mem::{replace, take},
13};
14
15#[derive(Debug)]
43pub struct LimitedQueue<T> {
44 q: Vec<Option<T>>,
45 front: usize,
46 rear: usize,
47 sz: usize,
48}
49
50impl<T> LimitedQueue<T> {
51 #[inline]
72 pub fn with_capacity(cap: usize) -> LimitedQueue<T> {
73 if cap == 0 {
74 panic!("Cannot create a LimitedQueue with zero capacity");
75 }
76 let mut q = Vec::with_capacity(cap);
77 q.resize_with(cap, Option::default);
78
79 LimitedQueue {
80 q,
81 front: 0usize,
82 rear: 0usize,
83 sz: 0usize,
84 }
85 }
86
87 #[inline]
98 pub fn get(&self, idx: usize) -> Option<&T> {
99 if idx >= self.sz {
100 None
101 } else {
102 Some(&self[idx])
103 }
104 }
105
106 #[inline]
119 pub fn peek(&self) -> Option<&T> {
120 if self.is_empty() {
121 None
122 } else {
123 self.q[self.front].as_ref()
124 }
125 }
126
127 #[inline]
130 pub fn push(&mut self, ele: T) -> Option<T> {
131 let mut popped = None;
132 if self.is_full() {
133 popped = replace(&mut self.q[self.rear], Some(ele));
136 self.front = self.next_idx(self.front);
138 } else {
139 let _ = std::mem::replace(&mut self.q[self.rear], Some(ele));
140 self.sz += 1;
141 }
142 self.rear = self.next_idx(self.rear);
143 popped
144 }
145
146 #[inline]
148 fn next_idx(&self, idx: usize) -> usize {
149 (idx + 1) % self.q.capacity()
150 }
151
152 #[inline]
153 pub fn is_empty(&self) -> bool {
154 self.sz == 0
155 }
156
157 #[inline]
158 pub fn is_full(&self) -> bool {
159 self.sz == self.q.capacity()
160 }
161
162 #[inline]
179 pub fn len(&self) -> usize {
180 self.sz
181 }
182
183 #[inline]
200 pub fn iter(&self) -> LimitedQueueIterator<T> {
201 LimitedQueueIterator {
202 lq: self,
203 front_idx: 0,
204 back_idx: self.sz,
205 }
206 }
207
208 #[inline]
228 pub fn iter_mut(&mut self) -> LimitedQueueIteratorMut<T> {
229 let len = self.sz;
230 let cap = self.q.capacity();
231 let front = self.front;
232 let q_ptr = self.q.as_mut_ptr(); LimitedQueueIteratorMut {
234 q_ptr,
235 front,
236 capacity: cap,
237 front_idx: 0,
238 back_idx: len,
239 _marker: PhantomData, }
241 }
242
243 #[inline]
257 pub fn clear(&mut self) {
258 self.front = 0;
259 self.rear = 0;
260 self.sz = 0;
261 }
262
263 #[inline]
265 fn indexing(&self, idx: usize) -> usize {
266 if idx >= self.sz {
267 panic!("Invalid subscription index: {}", idx)
268 }
269 (idx + self.front) % self.q.capacity()
270 }
271
272 #[inline]
285 pub fn pop(&mut self) -> Option<T> {
286 if self.is_empty() {
287 None
288 } else {
289 let ret = take(&mut self.q[self.front]);
290 self.front = self.next_idx(self.front);
291 self.sz -= 1;
292 ret
293 }
294 }
295}
296
297impl<T> std::ops::Index<usize> for LimitedQueue<T> {
298 type Output = T;
299
300 #[inline]
301 fn index(&self, idx: usize) -> &Self::Output {
302 let real_idx = self.indexing(idx);
303 self.q[real_idx].as_ref().unwrap()
304 }
305}
306
307impl<T> std::ops::IndexMut<usize> for LimitedQueue<T> {
308 #[inline]
309 fn index_mut(&mut self, idx: usize) -> &mut Self::Output {
310 let real_idx = self.indexing(idx);
311 self.q[real_idx].as_mut().unwrap()
312 }
313}
314
315pub struct LimitedQueueIterator<'a, T> {
316 lq: &'a LimitedQueue<T>,
317 front_idx: usize,
318 back_idx: usize,
319}
320
321#[cfg(not(tarpaulin_include))]
322impl<'a, T> Iterator for LimitedQueueIterator<'a, T> {
323 type Item = &'a T;
324
325 fn next(&mut self) -> Option<Self::Item> {
326 if self.front_idx == self.back_idx {
327 None } else {
329 let cur_idx = self.front_idx;
330 self.front_idx += 1;
331 Some(&self.lq[cur_idx])
332 }
333 }
334}
335
336impl<'a, T> DoubleEndedIterator for LimitedQueueIterator<'a, T> {
337 fn next_back(&mut self) -> Option<Self::Item> {
338 if self.front_idx == self.back_idx {
339 None } else {
341 self.back_idx -= 1;
342 let cur_idx = self.back_idx;
343 Some(&self.lq[cur_idx])
344 }
345 }
346}
347
348pub struct LimitedQueueIteratorMut<'a, T> {
350 q_ptr: *mut Option<T>, front: usize, capacity: usize,
353 front_idx: usize, back_idx: usize, _marker: PhantomData<&'a mut T>, }
357
358impl<'a, T> Iterator for LimitedQueueIteratorMut<'a, T> {
359 type Item = &'a mut T;
360
361 fn next(&mut self) -> Option<Self::Item> {
362 if self.front_idx == self.back_idx {
363 None
364 } else {
365 let cur_idx = self.front_idx;
366 self.front_idx += 1;
367 let real_idx = (cur_idx + self.front) % self.capacity;
368
369 unsafe {
370 let elem_ptr = self.q_ptr.add(real_idx);
372
373 let opt_ref = &mut *elem_ptr;
379
380 Some(opt_ref.as_mut().unwrap())
384 }
385 }
386 }
387}
388
389impl<'a, T> DoubleEndedIterator for LimitedQueueIteratorMut<'a, T> {
390 fn next_back(&mut self) -> Option<Self::Item> {
391 if self.front_idx == self.back_idx {
392 None
393 } else {
394 self.back_idx -= 1;
396 let cur_idx = self.back_idx;
397 let real_idx = (cur_idx + self.front) % self.capacity;
398
399 unsafe {
400 let elem_ptr = self.q_ptr.add(real_idx);
401 let opt_ref = &mut *elem_ptr;
402
403 Some(opt_ref.as_mut().unwrap())
405 }
406 }
407 }
408}
409
410#[cfg(test)]
411mod tests {
412 use std::panic;
413
414 use rand::Rng;
415
416 use crate::LimitedQueue;
417
418 #[derive(Debug, PartialEq, Eq, Clone)]
420 struct NoDefault(i32);
421
422 #[test]
423 fn test_pop_no_default() {
424 let mut q = LimitedQueue::with_capacity(2);
425 q.push(NoDefault(1));
426 q.push(NoDefault(2));
427 assert_eq!(q.push(NoDefault(3)), Some(NoDefault(1)));
428 assert_eq!(q.peek(), Some(&NoDefault(2)));
429 assert_eq!(q.pop(), Some(NoDefault(2)));
430 assert_eq!(q.pop(), Some(NoDefault(3)));
431 assert_eq!(q.pop(), None);
432 }
433
434 #[test]
435 fn test_iter() {
436 let mut q = crate::LimitedQueue::with_capacity(5);
437 let push_ret = [[None; 5], core::array::from_fn(|i| Some(i))].concat();
439 for (i, pr) in (0..10).zip(push_ret) {
440 assert_eq!(q.push(i), pr);
441 }
442 assert_eq!(q.len(), 5);
443 for (n, element) in q.iter().enumerate() {
444 assert_eq!(element.clone(), q[n]); assert_eq!(element.clone(), n + 5); }
447
448 for (n, element) in q.iter().rev().enumerate() {
450 assert_eq!(element.clone(), q[4 - n]); assert_eq!(element.clone(), 9 - n); }
453 }
454
455 #[test]
456 fn test_iter_mut() {
457 let mut q = LimitedQueue::with_capacity(5);
458 for i in 0..5 {
459 q.push(i); }
461
462 for element in q.iter_mut() {
463 *element += 10;
464 }
465
466 for (n, element) in q.iter().enumerate() {
468 assert_eq!(*element, n + 10);
469 }
470
471 assert_eq!(q.push(99), Some(10)); assert_eq!(q.peek(), Some(&11));
474 }
475
476 #[test]
477 fn test_double_ended_iter_mut() {
478 let mut q = LimitedQueue::with_capacity(5);
479 for i in 0..5 {
480 q.push(i); }
482
483 let mut iter_mut = q.iter_mut();
485 *iter_mut.next().unwrap() = 100; *iter_mut.next_back().unwrap() = 400; *iter_mut.next().unwrap() = 200; *iter_mut.next_back().unwrap() = 300; let mut iter = q.iter();
493 assert_eq!(iter.next(), Some(&100));
494 assert_eq!(iter.next(), Some(&200));
495 assert_eq!(iter.next(), Some(&2));
496 assert_eq!(iter.next(), Some(&300));
497 assert_eq!(iter.next(), Some(&400));
498 assert_eq!(iter.next(), None);
499 }
500
501 #[test]
502 fn test_change_size() {
503 const MAX_SZ: usize = 25;
504 let mut q: LimitedQueue<i32> = crate::LimitedQueue::with_capacity(MAX_SZ);
505 let mut sz = 0;
506 let mut rng = rand::thread_rng();
507
508 for _ in 0..1000 {
509 let op = rng.gen_range(0..=2);
510 match op {
511 0 => {
512 if q.push(rng.gen()).is_none() {
513 sz += 1
514 };
515 }
516 1 => {
517 if q.pop().is_some() {
518 sz -= 1
519 };
520 }
521 _ => {
522 assert!(match sz {
523 0 => q.is_empty() && q.pop().is_none() && q.peek().is_none(),
524 MAX_SZ => q.is_full(),
525 _ => sz == q.len() && sz < MAX_SZ,
526 });
527 }
528 };
529 }
530 }
531
532 #[test]
533 #[should_panic]
534 fn test_zero_len_invalid_indexing() {
535 LimitedQueue::<i32>::with_capacity(0)[0];
536 }
537
538 #[test]
539 fn test_invalid_indexing() {
540 let old_hook = panic::take_hook();
542 panic::set_hook(Box::new(|_info| {}));
543
544 let mut q = LimitedQueue::with_capacity(5);
545 q.push(1);
546 for i in 5..100 {
547 let invalid_access = || q[i];
548 let should_be_false = panic::catch_unwind(invalid_access).is_err();
549 if !should_be_false {
550 panic::set_hook(old_hook);
552 panic!("Indexing with idx: {} cannot trigger panic.", i);
554 }
555 }
556
557 panic::set_hook(old_hook);
558 }
559
560 #[test]
561 fn test_clear() {
562 let mut q = LimitedQueue::with_capacity(10);
563
564 q.clear();
566 assert_eq!(q.len(), 0);
567 assert!(q.is_empty());
568
569 for _ in 0..3 {
571 q.push(1);
572 }
573 assert_eq!(q.len(), 3);
574 q.clear();
575 assert_eq!(q.len(), 0);
576 assert_eq!(q.peek(), None);
577 assert!(q.is_empty());
578
579 for i in 0..10 {
581 q.push(i);
582 }
583 assert!(q.is_full());
584 q.clear();
585 assert!(q.is_empty());
586 assert_eq!(q.len(), 0);
587 assert_eq!(q.peek(), None);
588
589 assert_eq!(q.push(100), None);
591 assert_eq!(q.len(), 1);
592 assert_eq!(q.peek(), Some(&100));
593 assert_eq!(q.pop(), Some(100));
594 assert_eq!(q.len(), 0);
595 assert!(q.is_empty());
596 }
597
598 #[test]
599 fn test_capacity_one() {
600 let mut q = LimitedQueue::with_capacity(1);
601 assert!(q.is_empty());
602 assert_eq!(q.push(1), None);
603 assert!(q.is_full());
604 assert_eq!(q.peek(), Some(&1));
605 assert_eq!(q.push(2), Some(1)); assert!(q.is_full());
607 assert_eq!(q.peek(), Some(&2));
608 assert_eq!(q.pop(), Some(2));
609 assert!(q.is_empty());
610 assert_eq!(q.peek(), None);
611 assert_eq!(q.pop(), None);
612 assert_eq!(q.push(3), None);
613 assert_eq!(q.len(), 1);
614 assert_eq!(q.peek(), Some(&3));
615 }
616
617 #[test]
618 #[should_panic]
619 fn test_capacity_zero_push_panic() {
620 let mut q = LimitedQueue::<i32>::with_capacity(0);
621 q.push(1); }
623
624 #[test]
625 fn test_get_method() {
626 let mut q = LimitedQueue::with_capacity(3);
627 assert_eq!(q.get(0), None); assert_eq!(q.get(1), None);
629
630 q.push(10); q.push(20); assert_eq!(q.get(0), Some(&10));
633 assert_eq!(q.get(1), Some(&20));
634 assert_eq!(q.get(2), None); q.push(30); assert_eq!(q.get(2), Some(&30));
638 assert_eq!(q.get(3), None);
639
640 q.push(40); assert_eq!(q.get(0), Some(&20));
642 assert_eq!(q.get(1), Some(&30));
643 assert_eq!(q.get(2), Some(&40));
644 assert_eq!(q.get(3), None); }
646
647 #[test]
648 fn test_iter_empty() {
649 let mut q = LimitedQueue::<i32>::with_capacity(5);
650 assert_eq!(q.iter().next(), None);
651 assert_eq!(q.iter().next_back(), None);
652 assert_eq!(q.iter_mut().next(), None);
653 assert_eq!(q.iter_mut().next_back(), None);
654 }
655
656 #[test]
657 fn test_iter_mixed() {
658 let mut q = LimitedQueue::with_capacity(5);
659 for i in 0..5 {
660 q.push(i); }
662
663 let mut iter = q.iter();
664 assert_eq!(iter.next(), Some(&0));
665 assert_eq!(iter.next_back(), Some(&4));
666 assert_eq!(iter.next(), Some(&1));
667 assert_eq!(iter.next_back(), Some(&3));
668 assert_eq!(iter.next(), Some(&2));
669 assert_eq!(iter.next(), None);
670 assert_eq!(iter.next_back(), None);
671 }
672
673 #[test]
674 fn test_index_mut() {
675 let mut q = LimitedQueue::with_capacity(3);
676 q.push(1);
677 q.push(2); q[0] = 100; q[1] = 200;
681
682 assert_eq!(q.get(0), Some(&100));
683 assert_eq!(q.get(1), Some(&200));
684 }
685
686 #[test]
687 fn test_debug_format() {
688 let mut q = LimitedQueue::with_capacity(3);
689 q.push(1);
690 q.push(2);
691
692 let formatted = format!("{:?}", q);
694 assert!(formatted.contains("LimitedQueue"));
695 assert!(formatted.contains("Some(1)"));
696 assert!(formatted.contains("Some(2)"));
697 }
698
699 #[test]
700 #[should_panic(expected = "Invalid subscription index: 1")]
701 fn test_indexing_panic_simple() {
702 let mut q = LimitedQueue::with_capacity(3);
703 q.push(1); let _ = q[1]; }
706}