radiate_utils/buff/
window.rs1#[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 if self.buffer.len() >= self.cap {
33 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}