termichart_data/
series.rs1#[derive(Debug, Clone)]
6pub struct DataSeries<T: Clone> {
7 buf: Vec<T>,
8 capacity: usize,
9 head: usize,
10 len: usize,
11}
12
13impl<T: Clone> DataSeries<T> {
14 pub fn new(capacity: usize) -> Self {
20 assert!(capacity > 0, "DataSeries capacity must be > 0");
21 Self {
22 buf: Vec::with_capacity(capacity),
23 capacity,
24 head: 0,
25 len: 0,
26 }
27 }
28
29 pub fn push(&mut self, item: T) {
33 if self.buf.len() < self.capacity {
34 self.buf.push(item);
36 self.len = self.buf.len();
37 } else {
39 self.buf[self.head] = item;
41 self.head = (self.head + 1) % self.capacity;
42 }
44 }
45
46 pub fn len(&self) -> usize {
48 self.len
49 }
50
51 pub fn is_empty(&self) -> bool {
53 self.len == 0
54 }
55
56 pub fn capacity(&self) -> usize {
58 self.capacity
59 }
60
61 pub fn get(&self, index: usize) -> Option<&T> {
65 if index >= self.len {
66 return None;
67 }
68 if self.len < self.capacity {
69 Some(&self.buf[index])
71 } else {
72 let actual = (self.head + index) % self.capacity;
74 Some(&self.buf[actual])
75 }
76 }
77
78 pub fn iter(&self) -> impl Iterator<Item = &T> {
80 let len = self.len;
81 let cap = self.capacity;
82 let head = if self.len < self.capacity { 0 } else { self.head };
83 let buf = &self.buf;
84 (0..len).map(move |i| {
85 let actual = (head + i) % cap;
86 &buf[actual]
87 })
88 }
89
90 pub fn as_slice(&self) -> Vec<T> {
92 self.iter().cloned().collect()
93 }
94
95 pub fn last(&self) -> Option<&T> {
97 if self.len == 0 {
98 return None;
99 }
100 if self.len < self.capacity {
101 Some(&self.buf[self.len - 1])
102 } else {
103 let idx = (self.head + self.capacity - 1) % self.capacity;
106 Some(&self.buf[idx])
107 }
108 }
109
110 pub fn clear(&mut self) {
112 self.buf.clear();
113 self.head = 0;
114 self.len = 0;
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use super::*;
121
122 #[test]
123 fn basic_push_and_get() {
124 let mut s = DataSeries::new(4);
125 s.push(10);
126 s.push(20);
127 s.push(30);
128 assert_eq!(s.len(), 3);
129 assert_eq!(s.get(0), Some(&10));
130 assert_eq!(s.get(1), Some(&20));
131 assert_eq!(s.get(2), Some(&30));
132 assert_eq!(s.get(3), None);
133 }
134
135 #[test]
136 fn wraps_around() {
137 let mut s = DataSeries::new(3);
138 s.push(1);
139 s.push(2);
140 s.push(3);
141 s.push(4); assert_eq!(s.len(), 3);
143 assert_eq!(s.get(0), Some(&2));
144 assert_eq!(s.get(1), Some(&3));
145 assert_eq!(s.get(2), Some(&4));
146 }
147
148 #[test]
149 fn iter_order() {
150 let mut s = DataSeries::new(3);
151 s.push(1);
152 s.push(2);
153 s.push(3);
154 s.push(4);
155 let v: Vec<_> = s.iter().copied().collect();
156 assert_eq!(v, vec![2, 3, 4]);
157 }
158
159 #[test]
160 fn as_slice_matches_iter() {
161 let mut s = DataSeries::new(3);
162 for i in 0..5 {
163 s.push(i);
164 }
165 let from_iter: Vec<_> = s.iter().copied().collect();
166 assert_eq!(s.as_slice(), from_iter);
167 }
168
169 #[test]
170 fn last_returns_newest() {
171 let mut s = DataSeries::new(3);
172 assert!(s.last().is_none());
173 s.push(1);
174 assert_eq!(s.last(), Some(&1));
175 s.push(2);
176 s.push(3);
177 s.push(4);
178 assert_eq!(s.last(), Some(&4));
179 }
180
181 #[test]
182 fn clear_resets() {
183 let mut s = DataSeries::new(3);
184 s.push(1);
185 s.push(2);
186 s.clear();
187 assert!(s.is_empty());
188 assert_eq!(s.len(), 0);
189 assert!(s.get(0).is_none());
190 }
191
192 #[test]
193 fn capacity_is_correct() {
194 let s: DataSeries<i32> = DataSeries::new(10);
195 assert_eq!(s.capacity(), 10);
196 }
197
198 #[test]
199 #[should_panic]
200 fn zero_capacity_panics() {
201 let _s: DataSeries<i32> = DataSeries::new(0);
202 }
203}