1use std::fmt;
2
3#[derive(Debug, PartialEq)]
5pub enum BufferError {
6 BufferFull,
8}
9
10impl fmt::Display for BufferError {
11 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12 match self {
13 Self::BufferFull => write!(f, "circular buffer: cannot push, buffer is full"),
14 }
15 }
16}
17
18impl std::error::Error for BufferError {}
19
20#[derive(Debug, Clone)]
21pub struct CircularBuffer<T> {
22 buffer: Vec<Option<T>>,
23 front: usize,
24 rear: usize,
25 capacity: usize,
26 len: usize,
27}
28
29impl<T> CircularBuffer<T> {
30 pub fn new(size: usize) -> Self {
32 let mut buffer = Vec::with_capacity(size);
33 for _ in 0..size {
34 buffer.push(None);
35 }
36 CircularBuffer {
37 buffer,
38 front: 0,
39 rear: 0,
40 capacity: size,
41 len: 0,
42 }
43 }
44
45 pub fn push(&mut self, value: T) -> Result<(), BufferError> {
48 if self.is_full() {
49 return Err(BufferError::BufferFull);
50 }
51
52 self.buffer[self.rear] = Some(value);
53 self.rear = (self.rear + 1) % self.capacity;
54 self.len += 1;
55 Ok(())
56 }
57
58 pub fn pop(&mut self) -> Option<T> {
60 if self.is_empty() {
61 return None;
62 }
63
64 let value = self.buffer[self.front]
65 .take()
66 .expect("Buffer invariant violated: None value in non-empty buffer");
67 self.front = (self.front + 1) % self.capacity;
68 self.len -= 1;
69 Some(value)
70 }
71
72 pub fn len(&self) -> usize {
74 self.len
75 }
76
77 pub fn is_empty(&self) -> bool {
79 self.len == 0
80 }
81
82 pub fn is_full(&self) -> bool {
84 self.len == self.capacity
85 }
86
87 pub fn get(&self, index: usize) -> Option<&T> {
90 if index >= self.len {
91 return None;
92 }
93
94 let absolute_index = (self.front + index) % self.capacity;
95 self.buffer[absolute_index].as_ref()
96 }
97
98 pub fn remove_multiple(&mut self, count: usize) {
100 let count_to_remove = if count > self.len { self.len } else { count };
101
102 for _ in 0..count_to_remove {
103 self.buffer[self.front] = None;
104 self.front = (self.front + 1) % self.capacity;
105 self.len -= 1;
106 }
107 }
108}
109
110pub struct CircularBufferIntoIter<T> {
112 buffer: Vec<Option<T>>,
113 front: usize,
114 capacity: usize,
115 current: usize,
116 remaining: usize,
117}
118
119impl<T> Iterator for CircularBufferIntoIter<T> {
120 type Item = T;
121
122 fn next(&mut self) -> Option<Self::Item> {
123 if self.remaining == 0 {
124 return None;
125 }
126
127 let index = (self.front + self.current) % self.capacity;
128 self.current += 1;
129 self.remaining -= 1;
130
131 self.buffer[index].take()
132 }
133}
134
135impl<T> IntoIterator for CircularBuffer<T> {
136 type Item = T;
137 type IntoIter = CircularBufferIntoIter<T>;
138
139 fn into_iter(self) -> Self::IntoIter {
140 CircularBufferIntoIter {
141 buffer: self.buffer,
142 front: self.front,
143 capacity: self.capacity,
144 current: 0,
145 remaining: self.len,
146 }
147 }
148}