1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/// Append only data structure, replace oldest element when reach maximum capacity of `N` elements
#[derive(Debug, Clone)]
pub struct Ring<T, const N: usize> {
    data: [T; N],
    next: usize,
    len: usize,
}

/// Iterator over `Ring` starting from the oldest element
#[derive(Debug)]
pub struct RingIterator<'a, T, const N: usize> {
    start: usize,
    count: usize,
    circular: &'a Ring<T, N>,
}

impl<T: Copy + Default, const N: usize> Default for Ring<T, N> {
    fn default() -> Self {
        Self::new()
    }
}

impl<T: Copy + Default, const N: usize> Ring<T, N> {
    /// Creates a new `Ring` of give size `N`
    pub fn new() -> Self {
        Ring {
            data: [T::default(); N],
            next: 0usize,
            len: 0usize,
        }
    }

    fn increment_next(&mut self) {
        self.next = (self.next + 1) % self.data.len()
    }

    /// Append an element to the `Ring`, if there are already `N` elements, it replaces the oldest.
    pub fn append(&mut self, el: T) {
        self.data[self.next] = el;
        self.len = self.data.len().min(self.len + 1);
        self.increment_next()
    }

    /// Number of elements in the `Ring`, it never decreases.
    pub fn len(&self) -> usize {
        self.len
    }

    /// If the `Ring` is empty. Zero elements
    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    /// Return the max size of the ring
    pub fn size(&self) -> usize {
        N
    }

    /// Return the last item inserted
    pub fn last(&self) -> Option<T> {
        if self.len == 0 {
            None
        } else if self.next == 0 {
            Some(self.data[self.data.len() - 1])
        } else {
            Some(self.data[self.next - 1])
        }
    }

    /// Returns an iterator over the `Ring` starting from the oldest appended element
    pub fn iter(&self) -> RingIterator<T, N> {
        RingIterator {
            circular: &self,
            start: if self.len() == self.data.len() {
                self.next
            } else {
                0
            },
            count: 0usize,
        }
    }
}

impl<'a, T: Copy + Default, const N: usize> Iterator for RingIterator<'a, T, N> {
    type Item = T;
    fn next(&mut self) -> Option<T> {
        let len = self.circular.len();
        if self.count == len {
            return None;
        }
        let current_index = (self.start + self.count) % len;
        let result = self.circular.data[current_index];
        self.count += 1;
        Some(result)
    }
}

#[cfg(test)]
mod test {
    use super::Ring;

    const RING_SIZE: usize = 256;

    #[test]
    pub fn test_ring() {
        let mut circ: Ring<u32, RING_SIZE> = Ring::new();
        assert_eq!(circ.last(), None);
        assert_eq!(0, circ.len());
        circ.append(1u32);
        assert_eq!(circ.last(), Some(1));
        assert_eq!(1, circ.len());
        circ.append(2);
        circ.append(3);

        let mut iter = circ.iter();

        assert_eq!(iter.next(), Some(1));
        assert_eq!(iter.next(), Some(2));
        assert_eq!(iter.next(), Some(3));
        assert_eq!(iter.next(), None);
        assert_eq!(3, circ.len());
        for i in 0..1000 {
            circ.append(i);
            assert_eq!(circ.last(), Some(i));
        }
        assert_eq!(RING_SIZE, circ.len());

        let mut iter = circ.iter();

        for i in (1000 - RING_SIZE as u32)..1000 {
            assert_eq!(iter.next(), Some(i));
        }
        assert_eq!(iter.next(), None);
    }
}