cool_asserts/
iterators.rs

1use 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}