refraction_types/
ring_buffer.rs1use crate::{
2 BOUNDED_RING_BUFFER_DEFAULT_SIZE,
3 ring_iter::{IntoIter, Iter, IterMut},
4};
5
6#[derive(Debug, Clone)]
7pub struct BoundedRingBuffer<T> {
8 pub(crate) data: Vec<T>,
9 pub(crate) get_idx: usize,
10 pub(crate) put_idx: usize,
11 pub(crate) capacity: usize,
12 pub(crate) len: usize,
13}
14
15impl<T> BoundedRingBuffer<T>
16where
17 T: Copy + Default,
18{
19 #[must_use]
21 pub fn new() -> Self {
22 Self::with_capacity(BOUNDED_RING_BUFFER_DEFAULT_SIZE)
23 }
24
25 #[must_use]
31 pub fn with_capacity(cap: usize) -> Self {
32 assert_ne!(cap, 0, "Capacity cannot be zero!");
33 Self {
34 data: vec![T::default(); cap],
35 put_idx: 0,
36 get_idx: 0,
37 capacity: cap,
38 len: 0,
39 }
40 }
41
42 #[must_use]
44 pub fn len(&self) -> usize {
45 self.len
46 }
47
48 #[must_use]
50 pub fn capacity(&self) -> usize {
51 self.capacity
52 }
53
54 #[must_use]
56 pub fn get_idx(&self) -> usize {
57 self.get_idx
58 }
59
60 #[must_use]
62 pub fn put_idx(&self) -> usize {
63 self.put_idx
64 }
65
66 #[must_use]
68 pub fn is_empty(&self) -> bool {
69 self.get_idx == self.put_idx && self.len == 0
70 }
71
72 #[must_use]
74 pub fn iter(&self) -> Iter<'_, T> {
75 if self.is_empty() {
76 return Iter([].iter().chain([].iter()));
77 }
78
79 let (first, second) = self.as_slice();
80
81 let second_iter = match second {
82 Some(slice) => slice.iter(),
83 None => [].iter(),
84 };
85
86 Iter(first.iter().chain(second_iter))
87 }
88
89 #[must_use]
91 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
92 if self.is_empty() {
93 return IterMut([].iter_mut().chain([].iter_mut()));
94 }
95
96 let (first, second) = self.as_mut_slice();
97
98 let second_iter = match second {
99 Some(slice) => slice.iter_mut(),
100 None => [].iter_mut(),
101 };
102
103 IterMut(first.iter_mut().chain(second_iter))
104 }
105
106 #[must_use]
110 pub fn full(&self) -> bool {
111 self.get_idx == self.put_idx && self.len == self.capacity
112 }
113
114 #[must_use]
118 pub fn back(&self) -> Option<&T> {
119 if self.is_empty() {
120 None
121 } else {
122 Some(&self.data[(self.put_idx + self.capacity - 1) % self.capacity])
123 }
124 }
125
126 #[must_use]
130 pub fn back_mut(&mut self) -> Option<&mut T> {
131 if self.is_empty() {
132 None
133 } else {
134 Some(&mut self.data[(self.put_idx + self.capacity - 1) % self.capacity])
135 }
136 }
137
138 #[must_use]
140 pub fn front(&self) -> Option<&T> {
141 if self.is_empty() {
142 None
143 } else {
144 Some(&self.data[self.get_idx])
145 }
146 }
147
148 #[must_use]
150 pub fn front_mut(&mut self) -> Option<&mut T> {
151 if self.is_empty() {
152 None
153 } else {
154 let idx = self.get_idx;
155 Some(&mut self.data[idx])
156 }
157 }
158
159 pub fn enqueue(&mut self, data: T) {
163 if self.full() {
164 self.get_idx = (self.get_idx + 1) % self.capacity;
165 } else {
166 self.len += 1;
167 }
168
169 self.data[self.put_idx] = data;
170 self.put_idx = (self.put_idx + 1) % self.capacity;
171 }
172
173 #[must_use]
175 pub fn dequeue(&mut self) -> Option<T> {
176 if self.is_empty() {
177 return None;
178 }
179
180 let item = self.data[self.get_idx];
181 self.get_idx = (self.get_idx + 1) % self.capacity;
182 self.len -= 1;
183
184 Some(item)
185 }
186
187 pub fn advance(&mut self, size: usize) {
191 let size = size.min(self.capacity);
192
193 let new_put_idx = (self.put_idx + size) % self.capacity;
194 let remaining_space = self.capacity - self.len;
195 let offset = size.saturating_sub(remaining_space);
196 let new_get_idx = (self.get_idx + offset) % self.capacity;
197
198 self.get_idx = new_get_idx;
199 self.put_idx = new_put_idx;
200 self.len = (self.len + size).min(self.capacity);
201 }
202
203 pub fn enqueue_slice(&mut self, data: &[T]) {
207 match data.len().cmp(&self.capacity) {
208 std::cmp::Ordering::Less => {
209 let new_put_idx = (self.put_idx + data.len()) % self.capacity;
210 let remaining_space = self.capacity - self.len;
211 let offset = data.len().saturating_sub(remaining_space);
212 let new_get_idx = (self.get_idx + offset) % self.capacity;
213
214 if new_put_idx < self.put_idx {
216 let middle = self.capacity - self.put_idx;
218 self.data[self.put_idx..].copy_from_slice(&data[0..middle]);
219 self.data[..new_put_idx].copy_from_slice(&data[middle..]);
220 } else {
221 self.data[self.put_idx..self.put_idx + data.len()].copy_from_slice(data);
222 }
223
224 self.get_idx = new_get_idx;
225 self.put_idx = new_put_idx;
226 self.len = (self.len + data.len()).min(self.capacity);
227 }
228 std::cmp::Ordering::Equal => {
229 self.data.copy_from_slice(data);
230 self.put_idx = 0;
231 self.get_idx = 0;
232 self.len = data.len();
233 }
234 std::cmp::Ordering::Greater => {
235 let new_data_len = data.len();
236 let start = new_data_len - self.capacity;
237 let new_data = &data[start..new_data_len];
238 self.enqueue_slice(new_data);
239 }
240 }
241 }
242
243 #[must_use]
251 pub fn dequeue_slice(&mut self, out_buffer: &mut [T], dequeue_size: usize) -> usize {
252 if self.is_empty() {
253 return 0;
254 }
255
256 assert!(
257 out_buffer.len() >= dequeue_size,
258 "Dequeue size cannot be greater than out buffer"
259 );
260
261 match dequeue_size.cmp(&self.len) {
262 std::cmp::Ordering::Less => {
263 let new_get_idx = (self.get_idx + dequeue_size) % self.capacity;
264
265 if new_get_idx < self.get_idx {
266 let middle = self.capacity - self.get_idx;
267 out_buffer[0..middle].copy_from_slice(&self.data[self.get_idx..]);
268 out_buffer[middle..dequeue_size].copy_from_slice(&self.data[..new_get_idx]);
269 } else {
270 out_buffer[0..dequeue_size]
271 .copy_from_slice(&self.data[self.get_idx..new_get_idx]);
272 }
273
274 self.get_idx = new_get_idx;
275 self.len -= dequeue_size;
276
277 dequeue_size
278 }
279 std::cmp::Ordering::Equal => {
280 if self.get_idx >= self.put_idx {
281 let middle = self.capacity - self.get_idx;
282 out_buffer[0..middle].copy_from_slice(&self.data[self.get_idx..]);
283 out_buffer[middle..dequeue_size].copy_from_slice(&self.data[..self.put_idx]);
284 } else {
285 out_buffer[0..dequeue_size]
286 .copy_from_slice(&self.data[self.get_idx..self.put_idx]);
287 }
288 self.get_idx = self.put_idx;
289 self.len = 0;
290 dequeue_size
291 }
292 std::cmp::Ordering::Greater => {
293 self.dequeue_slice(&mut out_buffer[0..self.len], self.len)
294 }
295 }
296 }
297
298 #[must_use]
300 pub fn as_slice(&self) -> (&[T], Option<&[T]>) {
301 if self.get_idx < self.put_idx {
302 (&self.data[self.get_idx..self.put_idx], None)
303 } else {
304 (&self.data[self.get_idx..], Some(&self.data[..self.put_idx]))
305 }
306 }
307
308 #[must_use]
310 pub fn as_mut_slice(&mut self) -> (&mut [T], Option<&mut [T]>) {
311 if self.get_idx < self.put_idx {
312 (&mut self.data[self.get_idx..self.put_idx], None)
313 } else {
314 let (left, right) = self.data.split_at_mut(self.get_idx);
315 (right, Some(&mut left[..self.put_idx]))
316 }
317 }
318}
319impl<T> IntoIterator for BoundedRingBuffer<T>
320where
321 T: Copy + Default,
322{
323 type Item = T;
324 type IntoIter = IntoIter<T>;
325
326 fn into_iter(self) -> Self::IntoIter {
327 IntoIter(self)
328 }
329}
330
331impl<'a, T> IntoIterator for &'a BoundedRingBuffer<T>
332where
333 T: Copy + Default,
334{
335 type Item = &'a T;
336 type IntoIter = Iter<'a, T>;
337
338 fn into_iter(self) -> Self::IntoIter {
339 self.iter()
340 }
341}
342
343impl<'a, T> IntoIterator for &'a mut BoundedRingBuffer<T>
344where
345 T: Copy + Default,
346{
347 type Item = &'a mut T;
348 type IntoIter = IterMut<'a, T>;
349
350 fn into_iter(self) -> Self::IntoIter {
351 self.iter_mut()
352 }
353}