prettyping_rs/
ring_buffer.rs1#[derive(Debug, Clone, PartialEq, Eq)]
2pub struct RingBuffer<T> {
3 data: Vec<Option<T>>,
4 head: usize,
5 len: usize,
6}
7
8impl<T> RingBuffer<T> {
9 #[must_use]
10 pub fn with_capacity(capacity: usize) -> Self {
11 Self {
12 data: std::iter::repeat_with(|| None).take(capacity).collect(),
13 head: 0,
14 len: 0,
15 }
16 }
17
18 #[must_use]
19 pub fn capacity(&self) -> usize {
20 self.data.len()
21 }
22
23 #[must_use]
24 pub fn len(&self) -> usize {
25 self.len
26 }
27
28 #[must_use]
29 pub fn is_empty(&self) -> bool {
30 self.len == 0
31 }
32
33 pub fn push(&mut self, value: T) -> Option<T> {
34 let capacity = self.capacity();
35 if capacity == 0 {
36 return Some(value);
37 }
38
39 if self.len < capacity {
40 let index = (self.head + self.len) % capacity;
41 self.data[index] = Some(value);
42 self.len += 1;
43 return None;
44 }
45
46 let index = self.head;
47 self.head = (self.head + 1) % capacity;
48 self.data[index].replace(value)
49 }
50
51 #[must_use]
52 pub fn iter(&self) -> RingBufferIter<'_, T> {
53 RingBufferIter {
54 buffer: self,
55 offset: 0,
56 }
57 }
58}
59
60pub struct RingBufferIter<'a, T> {
61 buffer: &'a RingBuffer<T>,
62 offset: usize,
63}
64
65impl<'a, T> Iterator for RingBufferIter<'a, T> {
66 type Item = &'a T;
67
68 fn next(&mut self) -> Option<Self::Item> {
69 if self.offset >= self.buffer.len {
70 return None;
71 }
72
73 let index = (self.buffer.head + self.offset) % self.buffer.capacity();
74 self.offset += 1;
75 self.buffer.data[index].as_ref()
76 }
77}
78
79#[cfg(test)]
80mod tests {
81 use super::RingBuffer;
82
83 #[test]
84 fn overwrites_oldest_value_when_full() {
85 let mut ring = RingBuffer::with_capacity(3);
86
87 assert_eq!(ring.push(1), None);
88 assert_eq!(ring.push(2), None);
89 assert_eq!(ring.push(3), None);
90 assert_eq!(ring.push(4), Some(1));
91
92 let values: Vec<i32> = ring.iter().copied().collect();
93 assert_eq!(values, vec![2, 3, 4]);
94 }
95
96 #[test]
97 fn empty_capacity_discards_values() {
98 let mut ring = RingBuffer::with_capacity(0);
99
100 assert_eq!(ring.push(42), Some(42));
101 assert!(ring.is_empty());
102 assert_eq!(ring.len(), 0);
103 assert_eq!(ring.capacity(), 0);
104 }
105}