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
136
137
138
139
140
// This file is part of the uutils coreutils package.
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//! A fixed-size ring buffer.
use std::collections::VecDeque;

/// A fixed-size ring buffer backed by a `VecDeque`.
///
/// If the ring buffer is not full, then calling the [`push_back`]
/// method appends elements, as in a [`VecDeque`]. If the ring buffer
/// is full, then calling [`push_back`] removes the element at the
/// front of the buffer (in a first-in, first-out manner) before
/// appending the new element to the back of the buffer.
///
/// Use [`from_iter`] to take the last `size` elements from an
/// iterator.
///
/// # Examples
///
/// After exceeding the size limit, the oldest elements are dropped in
/// favor of the newest element:
///
/// ```rust,ignore
/// let mut buffer: RingBuffer<u8> = RingBuffer::new(2);
/// buffer.push_back(0);
/// buffer.push_back(1);
/// buffer.push_back(2);
/// assert_eq!(vec![1, 2], buffer.data);
/// ```
///
/// Take the last `n` elements from an iterator:
///
/// ```rust,ignore
/// let iter = [0, 1, 2].iter();
/// let actual = RingBuffer::from_iter(iter, 2).data;
/// let expected = VecDeque::from_iter([1, 2].iter());
/// assert_eq!(expected, actual);
/// ```
///
/// [`push_back`]: struct.RingBuffer.html#method.push_back
/// [`from_iter`]: struct.RingBuffer.html#method.from_iter
pub struct RingBuffer<T> {
    pub data: VecDeque<T>,
    size: usize,
}

impl<T> RingBuffer<T> {
    pub fn new(size: usize) -> Self {
        Self {
            data: VecDeque::new(),
            size,
        }
    }

    pub fn from_iter(iter: impl Iterator<Item = T>, size: usize) -> Self {
        let mut ring_buffer = Self::new(size);
        for value in iter {
            ring_buffer.push_back(value);
        }
        ring_buffer
    }

    /// Append a value to the end of the ring buffer.
    ///
    /// If the ring buffer is not full, this method return [`None`]. If
    /// the ring buffer is full, appending a new element will cause the
    /// oldest element to be evicted. In that case this method returns
    /// that element, or `None`.
    ///
    /// In the special case where the size limit is zero, each call to
    /// this method with input `value` returns `Some(value)`, because
    /// the input is immediately evicted.
    ///
    /// # Examples
    ///
    /// Appending an element when the buffer is full returns the oldest
    /// element:
    ///
    /// ```rust,ignore
    /// let mut buf = RingBuffer::new(3);
    /// assert_eq!(None, buf.push_back(0));
    /// assert_eq!(None, buf.push_back(1));
    /// assert_eq!(None, buf.push_back(2));
    /// assert_eq!(Some(0), buf.push_back(3));
    /// ```
    ///
    /// If the size limit is zero, then this method always returns the
    /// input value:
    ///
    /// ```rust,ignore
    /// let mut buf = RingBuffer::new(0);
    /// assert_eq!(Some(0), buf.push_back(0));
    /// assert_eq!(Some(1), buf.push_back(1));
    /// assert_eq!(Some(2), buf.push_back(2));
    /// ```
    pub fn push_back(&mut self, value: T) -> Option<T> {
        if self.size == 0 {
            return Some(value);
        }
        let result = if self.size <= self.data.len() {
            self.data.pop_front()
        } else {
            None
        };
        self.data.push_back(value);
        result
    }
}

#[cfg(test)]
mod tests {

    use crate::ringbuffer::RingBuffer;
    use std::collections::VecDeque;

    #[test]
    fn test_size_limit_zero() {
        let mut buf = RingBuffer::new(0);
        assert_eq!(Some(0), buf.push_back(0));
        assert_eq!(Some(1), buf.push_back(1));
        assert_eq!(Some(2), buf.push_back(2));
    }

    #[test]
    fn test_evict_oldest() {
        let mut buf = RingBuffer::new(2);
        assert_eq!(None, buf.push_back(0));
        assert_eq!(None, buf.push_back(1));
        assert_eq!(Some(0), buf.push_back(2));
    }

    #[test]
    fn test_from_iter() {
        let iter = [0, 1, 2].iter();
        let actual = RingBuffer::from_iter(iter, 2).data;
        let expected: VecDeque<&i32> = [1, 2].iter().collect();
        assert_eq!(expected, actual);
    }
}