e_ring/
ring.rs

1/// Append only data structure, replace oldest element when reach maximum capacity of `N` elements
2#[derive(Debug, Clone)]
3pub struct Ring<T, const N: usize> {
4    data: [T; N],
5    next: usize,
6    len: usize,
7}
8
9/// Iterator over `Ring` starting from the oldest element
10#[derive(Debug)]
11pub struct RingIterator<'a, T, const N: usize> {
12    start: usize,
13    count: usize,
14    circular: &'a Ring<T, N>,
15}
16
17impl<T: Copy + Default, const N: usize> Default for Ring<T, N> {
18    fn default() -> Self {
19        Self::new()
20    }
21}
22
23impl<T: Copy + Default, const N: usize> Ring<T, N> {
24    /// Creates a new `Ring` of give size `N`
25    pub fn new() -> Self {
26        Ring {
27            data: [T::default(); N],
28            next: 0usize,
29            len: 0usize,
30        }
31    }
32
33    fn increment_next(&mut self) {
34        self.next = (self.next + 1) % self.data.len()
35    }
36
37    /// Append an element to the `Ring`, if there are already `N` elements, it replaces the oldest.
38    pub fn append(&mut self, el: T) {
39        self.data[self.next] = el;
40        self.len = self.data.len().min(self.len + 1);
41        self.increment_next()
42    }
43
44    /// Number of elements in the `Ring`, it never decreases.
45    pub fn len(&self) -> usize {
46        self.len
47    }
48
49    /// If the `Ring` is empty. Zero elements
50    pub fn is_empty(&self) -> bool {
51        self.len == 0
52    }
53
54    /// Return the max size of the ring
55    pub fn size(&self) -> usize {
56        N
57    }
58
59    /// Return the last item inserted
60    pub fn last(&self) -> Option<T> {
61        if self.len == 0 {
62            None
63        } else if self.next == 0 {
64            Some(self.data[self.data.len() - 1])
65        } else {
66            Some(self.data[self.next - 1])
67        }
68    }
69
70    /// Returns an iterator over the `Ring` starting from the oldest appended element
71    pub fn iter(&self) -> RingIterator<T, N> {
72        RingIterator {
73            circular: self,
74            start: if self.len() == self.data.len() {
75                self.next
76            } else {
77                0
78            },
79            count: 0usize,
80        }
81    }
82}
83
84impl<'a, T: Copy + Default, const N: usize> Iterator for RingIterator<'a, T, N> {
85    type Item = T;
86    fn next(&mut self) -> Option<T> {
87        let len = self.circular.len();
88        if self.count == len {
89            return None;
90        }
91        let current_index = (self.start + self.count) % len;
92        let result = self.circular.data[current_index];
93        self.count += 1;
94        Some(result)
95    }
96}
97
98#[cfg(test)]
99mod test {
100    use super::Ring;
101
102    const RING_SIZE: usize = 256;
103
104    #[test]
105    pub fn test_ring() {
106        let mut circ: Ring<u32, RING_SIZE> = Ring::new();
107        assert_eq!(circ.last(), None);
108        assert_eq!(0, circ.len());
109        circ.append(1u32);
110        assert_eq!(circ.last(), Some(1));
111        assert_eq!(1, circ.len());
112        circ.append(2);
113        circ.append(3);
114
115        let mut iter = circ.iter();
116
117        assert_eq!(iter.next(), Some(1));
118        assert_eq!(iter.next(), Some(2));
119        assert_eq!(iter.next(), Some(3));
120        assert_eq!(iter.next(), None);
121        assert_eq!(3, circ.len());
122        for i in 0..1000 {
123            circ.append(i);
124            assert_eq!(circ.last(), Some(i));
125        }
126        assert_eq!(RING_SIZE, circ.len());
127
128        let mut iter = circ.iter();
129
130        for i in (1000 - RING_SIZE as u32)..1000 {
131            assert_eq!(iter.next(), Some(i));
132        }
133        assert_eq!(iter.next(), None);
134    }
135}