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 pub fn consume(&mut self, n: usize) {
112 let n = n.min(self.len);
113 self.get_idx = (self.get_idx + n) % self.capacity;
114 self.len -= n;
115 }
116
117 #[must_use]
119 pub fn full(&self) -> bool {
120 self.get_idx == self.put_idx && self.len == self.capacity
121 }
122
123 #[must_use]
127 pub fn back(&self) -> Option<&T> {
128 if self.is_empty() {
129 None
130 } else {
131 Some(&self.data[(self.put_idx + self.capacity - 1) % self.capacity])
132 }
133 }
134
135 #[must_use]
139 pub fn back_mut(&mut self) -> Option<&mut T> {
140 if self.is_empty() {
141 None
142 } else {
143 Some(&mut self.data[(self.put_idx + self.capacity - 1) % self.capacity])
144 }
145 }
146
147 #[must_use]
149 pub fn front(&self) -> Option<&T> {
150 if self.is_empty() {
151 None
152 } else {
153 Some(&self.data[self.get_idx])
154 }
155 }
156
157 #[must_use]
159 pub fn front_mut(&mut self) -> Option<&mut T> {
160 if self.is_empty() {
161 None
162 } else {
163 let idx = self.get_idx;
164 Some(&mut self.data[idx])
165 }
166 }
167
168 pub fn enqueue(&mut self, data: T) {
172 if self.full() {
173 self.get_idx = (self.get_idx + 1) % self.capacity;
174 } else {
175 self.len += 1;
176 }
177
178 self.data[self.put_idx] = data;
179 self.put_idx = (self.put_idx + 1) % self.capacity;
180 }
181
182 #[must_use]
184 pub fn dequeue(&mut self) -> Option<T> {
185 if self.is_empty() {
186 return None;
187 }
188
189 let item = self.data[self.get_idx];
190 self.get_idx = (self.get_idx + 1) % self.capacity;
191 self.len -= 1;
192
193 Some(item)
194 }
195
196 pub fn advance(&mut self, size: usize) {
200 let size = size.min(self.capacity);
201
202 let new_put_idx = (self.put_idx + size) % self.capacity;
203 let remaining_space = self.capacity - self.len;
204 let offset = size.saturating_sub(remaining_space);
205 let new_get_idx = (self.get_idx + offset) % self.capacity;
206
207 self.get_idx = new_get_idx;
208 self.put_idx = new_put_idx;
209 self.len = (self.len + size).min(self.capacity);
210 }
211
212 pub fn enqueue_slice(&mut self, data: &[T]) {
218 match data.len().cmp(&self.capacity) {
219 std::cmp::Ordering::Less => {
220 let new_put_idx = (self.put_idx + data.len()) % self.capacity;
221 let remaining_space = self.capacity - self.len;
222 let offset = data.len().saturating_sub(remaining_space);
223 let new_get_idx = (self.get_idx + offset) % self.capacity;
224
225 if new_put_idx < self.put_idx {
227 let middle = self.capacity - self.put_idx;
229 self.data[self.put_idx..].copy_from_slice(&data[0..middle]);
230 self.data[..new_put_idx].copy_from_slice(&data[middle..]);
231 } else {
232 self.data[self.put_idx..self.put_idx + data.len()].copy_from_slice(data);
233 }
234
235 self.get_idx = new_get_idx;
236 self.put_idx = new_put_idx;
237 self.len = (self.len + data.len()).min(self.capacity);
238 }
239 std::cmp::Ordering::Equal => {
240 self.data.copy_from_slice(data);
241 self.put_idx = 0;
242 self.get_idx = 0;
243 self.len = data.len();
244 }
245 std::cmp::Ordering::Greater => {
246 let new_data_len = data.len();
247 let start = new_data_len - self.capacity;
248 let new_data = &data[start..new_data_len];
249 self.enqueue_slice(new_data);
250 }
251 }
252 }
253
254 #[must_use]
264 pub fn dequeue_slice(&mut self, out_buffer: &mut [T], dequeue_size: usize) -> usize {
265 if self.is_empty() {
266 return 0;
267 }
268
269 assert!(
270 out_buffer.len() >= dequeue_size,
271 "Dequeue size cannot be greater than out buffer"
272 );
273
274 match dequeue_size.cmp(&self.len) {
275 std::cmp::Ordering::Less => {
276 let new_get_idx = (self.get_idx + dequeue_size) % self.capacity;
277
278 if new_get_idx < self.get_idx {
279 let middle = self.capacity - self.get_idx;
280 out_buffer[0..middle].copy_from_slice(&self.data[self.get_idx..]);
281 out_buffer[middle..dequeue_size].copy_from_slice(&self.data[..new_get_idx]);
282 } else {
283 out_buffer[0..dequeue_size]
284 .copy_from_slice(&self.data[self.get_idx..new_get_idx]);
285 }
286
287 self.get_idx = new_get_idx;
288 self.len -= dequeue_size;
289
290 dequeue_size
291 }
292 std::cmp::Ordering::Equal => {
293 if self.get_idx >= self.put_idx {
294 let middle = self.capacity - self.get_idx;
295 out_buffer[0..middle].copy_from_slice(&self.data[self.get_idx..]);
296 out_buffer[middle..dequeue_size].copy_from_slice(&self.data[..self.put_idx]);
297 } else {
298 out_buffer[0..dequeue_size]
299 .copy_from_slice(&self.data[self.get_idx..self.put_idx]);
300 }
301 self.get_idx = self.put_idx;
302 self.len = 0;
303 dequeue_size
304 }
305 std::cmp::Ordering::Greater => {
306 self.dequeue_slice(&mut out_buffer[0..self.len], self.len)
307 }
308 }
309 }
310
311 #[must_use]
316 pub fn try_peek_slice(&self, offset: usize, len: usize) -> Option<&[T]> {
317 if offset + len > self.len {
318 return None;
319 }
320 let start = (self.get_idx + offset) % self.capacity;
321 let end = start + len;
322 if end <= self.capacity {
323 Some(&self.data[start..end])
324 } else {
325 None
326 }
327 }
328
329 #[must_use]
337 pub fn copy_out(&self, offset: usize, out: &mut [T]) -> usize {
338 if self.is_empty() {
339 return 0;
340 }
341
342 if offset + out.len() > self.len {
343 return 0;
344 }
345
346 let len = out.len();
347 let start = (self.get_idx + offset) % self.capacity;
348 let end = start + len;
349 if end <= self.capacity {
350 out.copy_from_slice(&self.data[start..end]);
351 } else {
352 let middle = self.capacity - start;
353 let wrapped_end = end - self.capacity;
354 out[..middle].copy_from_slice(&self.data[start..]);
355 out[middle..].copy_from_slice(&self.data[..wrapped_end]);
356 }
357
358 out.len()
359 }
360
361 #[must_use]
363 pub fn as_slice(&self) -> (&[T], Option<&[T]>) {
364 if self.get_idx < self.put_idx {
365 (&self.data[self.get_idx..self.put_idx], None)
366 } else {
367 (&self.data[self.get_idx..], Some(&self.data[..self.put_idx]))
368 }
369 }
370
371 #[must_use]
373 pub fn as_mut_slice(&mut self) -> (&mut [T], Option<&mut [T]>) {
374 if self.get_idx < self.put_idx {
375 (&mut self.data[self.get_idx..self.put_idx], None)
376 } else {
377 let (left, right) = self.data.split_at_mut(self.get_idx);
378 (right, Some(&mut left[..self.put_idx]))
379 }
380 }
381}
382impl<T> IntoIterator for BoundedRingBuffer<T>
383where
384 T: Copy + Default,
385{
386 type Item = T;
387 type IntoIter = IntoIter<T>;
388
389 fn into_iter(self) -> Self::IntoIter {
390 IntoIter(self)
391 }
392}
393
394impl<'a, T> IntoIterator for &'a BoundedRingBuffer<T>
395where
396 T: Copy + Default,
397{
398 type Item = &'a T;
399 type IntoIter = Iter<'a, T>;
400
401 fn into_iter(self) -> Self::IntoIter {
402 self.iter()
403 }
404}
405
406impl<'a, T> IntoIterator for &'a mut BoundedRingBuffer<T>
407where
408 T: Copy + Default,
409{
410 type Item = &'a mut T;
411 type IntoIter = IterMut<'a, T>;
412
413 fn into_iter(self) -> Self::IntoIter {
414 self.iter_mut()
415 }
416}