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_window(cap: usize) -> Self {
16        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 values(&self) -> &[T] {
69        &self.buffer[self.start..self.end]
70    }
71
72    pub fn iter(&self) -> impl Iterator<Item = &T> {
73        self.values().iter()
74    }
75
76    pub fn as_slice(&self) -> &[T] {
77        self.values()
78    }
79}
80
81impl<T: Clone> Clone for WindowBuffer<T> {
82    fn clone(&self) -> Self {
83        Self {
84            buffer: self.buffer.clone(),
85            cap: self.cap,
86            max: self.max,
87            start: self.start,
88            end: self.end,
89        }
90    }
91}
92
93impl<T: PartialEq> PartialEq for WindowBuffer<T> {
94    fn eq(&self, other: &Self) -> bool {
95        self.values() == other.values()
96    }
97}
98
99impl<T: Debug> Debug for WindowBuffer<T> {
100    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
101        f.debug_struct("WindowBuffer")
102            .field("capacity", &self.cap)
103            .field("values", &self.values())
104            .finish()
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::WindowBuffer;
111
112    #[test]
113    fn ring_buffer_works() {
114        let mut buffer = WindowBuffer::with_window(5);
115        for i in 0..20 {
116            buffer.push(i);
117        }
118    }
119}