cool_asserts/
iterators.rs1use std::{iter::FusedIterator, mem, ops::Add};
2
3#[derive(Debug, Clone)]
4pub struct LoopBuffer<T, const N: usize> {
5 buffer: [T; N],
6 head: usize,
7}
8
9impl<T, const N: usize> LoopBuffer<T, N> {
10 pub fn new(buffer: [T; N]) -> Self {
11 Self { buffer, head: 0 }
12 }
13
14 pub fn push(&mut self, item: T) -> T {
15 debug_assert!(self.head < N);
16 let old_item = mem::replace(unsafe { self.buffer.get_unchecked_mut(self.head) }, item);
17 self.head = self.head.add(1).rem_euclid(N);
18 old_item
19 }
20
21 pub fn bind_iterator<'a>(
22 &'a mut self,
23 iter: impl Iterator<Item = T> + 'a,
24 ) -> impl Iterator<Item = T> + 'a {
25 iter.map(move |item| self.push(item))
26 }
27
28 pub fn into_array(mut self) -> [T; N] {
29 self.buffer.rotate_left(self.head);
30 self.buffer
31 }
32}
33
34#[test]
35fn test_loop_buffer() {
36 let data = [3, 4, 5, 6];
37 let mut buffer = LoopBuffer::new(data);
38
39 let iterated: Vec<i32> = buffer.bind_iterator(7..).take(11).collect();
40
41 assert_eq!(iterated, [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]);
42 assert_eq!(buffer.into_array(), [14, 15, 16, 17])
43}
44
45#[inline(always)]
46#[doc(hidden)]
47pub fn erase_type<I: Iterator + FusedIterator>(
48 iter: I,
49) -> impl Iterator<Item = I::Item> + FusedIterator {
50 iter
51}