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]) {
209 match data.len().cmp(&self.capacity) {
210 std::cmp::Ordering::Less => {
211 let new_put_idx = (self.put_idx + data.len()) % self.capacity;
212 let remaining_space = self.capacity - self.len;
213 let offset = data.len().saturating_sub(remaining_space);
214 let new_get_idx = (self.get_idx + offset) % self.capacity;
215
216 if new_put_idx < self.put_idx {
218 let middle = self.capacity - self.put_idx;
220 self.data[self.put_idx..].copy_from_slice(&data[0..middle]);
221 self.data[..new_put_idx].copy_from_slice(&data[middle..]);
222 } else {
223 self.data[self.put_idx..self.put_idx + data.len()].copy_from_slice(data);
224 }
225
226 self.get_idx = new_get_idx;
227 self.put_idx = new_put_idx;
228 self.len = (self.len + data.len()).min(self.capacity);
229 }
230 std::cmp::Ordering::Equal => {
231 self.data.copy_from_slice(data);
232 self.put_idx = 0;
233 self.get_idx = 0;
234 self.len = data.len();
235 }
236 std::cmp::Ordering::Greater => {
237 let new_data_len = data.len();
238 let start = new_data_len - self.capacity;
239 let new_data = &data[start..new_data_len];
240 self.enqueue_slice(new_data);
241 }
242 }
243 }
244
245 #[must_use]
255 pub fn dequeue_slice(&mut self, out_buffer: &mut [T], dequeue_size: usize) -> usize {
256 if self.is_empty() {
257 return 0;
258 }
259
260 assert!(
261 out_buffer.len() >= dequeue_size,
262 "Dequeue size cannot be greater than out buffer"
263 );
264
265 match dequeue_size.cmp(&self.len) {
266 std::cmp::Ordering::Less => {
267 let new_get_idx = (self.get_idx + dequeue_size) % self.capacity;
268
269 if new_get_idx < self.get_idx {
270 let middle = self.capacity - self.get_idx;
271 out_buffer[0..middle].copy_from_slice(&self.data[self.get_idx..]);
272 out_buffer[middle..dequeue_size].copy_from_slice(&self.data[..new_get_idx]);
273 } else {
274 out_buffer[0..dequeue_size]
275 .copy_from_slice(&self.data[self.get_idx..new_get_idx]);
276 }
277
278 self.get_idx = new_get_idx;
279 self.len -= dequeue_size;
280
281 dequeue_size
282 }
283 std::cmp::Ordering::Equal => {
284 if self.get_idx >= self.put_idx {
285 let middle = self.capacity - self.get_idx;
286 out_buffer[0..middle].copy_from_slice(&self.data[self.get_idx..]);
287 out_buffer[middle..dequeue_size].copy_from_slice(&self.data[..self.put_idx]);
288 } else {
289 out_buffer[0..dequeue_size]
290 .copy_from_slice(&self.data[self.get_idx..self.put_idx]);
291 }
292 self.get_idx = self.put_idx;
293 self.len = 0;
294 dequeue_size
295 }
296 std::cmp::Ordering::Greater => {
297 self.dequeue_slice(&mut out_buffer[0..self.len], self.len)
298 }
299 }
300 }
301
302 #[must_use]
304 pub fn as_slice(&self) -> (&[T], Option<&[T]>) {
305 if self.get_idx < self.put_idx {
306 (&self.data[self.get_idx..self.put_idx], None)
307 } else {
308 (&self.data[self.get_idx..], Some(&self.data[..self.put_idx]))
309 }
310 }
311
312 #[must_use]
314 pub fn as_mut_slice(&mut self) -> (&mut [T], Option<&mut [T]>) {
315 if self.get_idx < self.put_idx {
316 (&mut self.data[self.get_idx..self.put_idx], None)
317 } else {
318 let (left, right) = self.data.split_at_mut(self.get_idx);
319 (right, Some(&mut left[..self.put_idx]))
320 }
321 }
322}
323impl<T> IntoIterator for BoundedRingBuffer<T>
324where
325 T: Copy + Default,
326{
327 type Item = T;
328 type IntoIter = IntoIter<T>;
329
330 fn into_iter(self) -> Self::IntoIter {
331 IntoIter(self)
332 }
333}
334
335impl<'a, T> IntoIterator for &'a BoundedRingBuffer<T>
336where
337 T: Copy + Default,
338{
339 type Item = &'a T;
340 type IntoIter = Iter<'a, T>;
341
342 fn into_iter(self) -> Self::IntoIter {
343 self.iter()
344 }
345}
346
347impl<'a, T> IntoIterator for &'a mut BoundedRingBuffer<T>
348where
349 T: Copy + Default,
350{
351 type Item = &'a mut T;
352 type IntoIter = IterMut<'a, T>;
353
354 fn into_iter(self) -> Self::IntoIter {
355 self.iter_mut()
356 }
357}