Skip to main content

radiate_utils/buff/
window.rs

1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3use std::fmt::Debug;
4
5#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6pub struct WindowBuffer<T> {
7    buffer: Vec<T>,
8    cap: usize,
9    max: usize,
10    start: usize,
11    end: usize,
12}
13
14impl<T> WindowBuffer<T> {
15    pub fn with_capacity(cap: usize) -> Self {
16        debug_assert!(cap > 0, "WindowBuffer capacity must be > 0");
17
18        let max = cap * 2;
19        Self {
20            buffer: Vec::with_capacity(max),
21            cap,
22            max,
23            start: 0,
24            end: 0,
25        }
26    }
27
28    #[inline]
29    pub fn push(&mut self, item: T) -> bool {
30        let mut resized = false;
31        // check if the buffer is at capacity
32        if self.buffer.len() >= self.cap {
33            // check if the buffer is full
34            if self.buffer.len() >= self.max {
35                if self.end >= self.max {
36                    let (front, back) = self.buffer.split_at_mut(self.cap);
37                    front.swap_with_slice(back);
38
39                    self.start = 0;
40                    self.end = self.cap;
41                }
42                self.buffer[self.end] = item;
43            } else {
44                self.buffer.push(item);
45            }
46
47            resized = true;
48
49            self.start += 1;
50            self.end += 1;
51        } else {
52            self.buffer.push(item);
53            self.end += 1;
54            if self.end - self.start > self.cap {
55                self.start += 1;
56            }
57        }
58
59        resized
60    }
61
62    #[inline]
63    pub fn len(&self) -> usize {
64        self.buffer.len().saturating_sub(self.start)
65    }
66
67    #[inline]
68    pub fn is_empty(&self) -> bool {
69        self.len() == 0
70    }
71
72    #[inline]
73    pub fn values(&self) -> &[T] {
74        &self.buffer[self.start..self.end]
75    }
76
77    pub fn iter(&self) -> impl Iterator<Item = &T> {
78        self.values().iter()
79    }
80
81    pub fn as_slice(&self) -> &[T] {
82        self.values()
83    }
84
85    pub fn clear(&mut self) {
86        self.buffer.clear();
87        self.start = 0;
88        self.end = 0;
89    }
90}
91
92impl<T: Clone> Clone for WindowBuffer<T> {
93    fn clone(&self) -> Self {
94        Self {
95            buffer: self.buffer.clone(),
96            cap: self.cap,
97            max: self.max,
98            start: self.start,
99            end: self.end,
100        }
101    }
102}
103
104impl<T: PartialEq> PartialEq for WindowBuffer<T> {
105    fn eq(&self, other: &Self) -> bool {
106        self.values() == other.values()
107    }
108}
109
110impl<T: Debug> Debug for WindowBuffer<T> {
111    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
112        f.debug_struct("WindowBuffer")
113            .field("capacity", &self.cap)
114            .field("values", &self.values())
115            .finish()
116    }
117}
118
119#[cfg(test)]
120mod tests {
121    use super::WindowBuffer;
122
123    #[test]
124    fn ring_buffer_works() {
125        let mut buffer = WindowBuffer::with_capacity(5);
126        for i in 0..20 {
127            buffer.push(i);
128        }
129    }
130}