1pub struct RingBuf<T: Copy + Default, const N: usize> {
27 buf: [T; N],
28 head: usize,
30 len: usize,
32}
33
34impl<T: Copy + Default, const N: usize> RingBuf<T, N> {
35 pub fn new() -> Self {
40 assert!(N > 0, "RingBuf capacity N must be > 0");
41 Self {
42 buf: [T::default(); N],
43 head: 0,
44 len: 0,
45 }
46 }
47
48 pub fn push(&mut self, val: T) {
53 self.buf[self.head] = val;
54 self.head = (self.head + 1) % N;
55 if self.len < N {
56 self.len += 1;
57 }
58 }
59
60 pub fn len(&self) -> usize {
62 self.len
63 }
64
65 pub fn is_empty(&self) -> bool {
67 self.len == 0
68 }
69
70 pub fn is_full(&self) -> bool {
73 self.len == N
74 }
75
76 #[inline]
78 pub const fn capacity(&self) -> usize {
79 N
80 }
81
82 pub fn clear(&mut self) {
87 self.head = 0;
88 self.len = 0;
89 }
90
91 pub fn get(&self, i: usize) -> Option<T> {
93 if i >= self.len {
94 return None;
95 }
96 let idx = if self.len < N { i } else { (self.head + i) % N };
97 Some(self.buf[idx])
98 }
99
100 pub fn latest(&self) -> Option<T> {
102 if self.len == 0 {
103 return None;
104 }
105 let idx = if self.head == 0 { N - 1 } else { self.head - 1 };
106 Some(self.buf[idx])
107 }
108
109 pub fn iter(&self) -> RingIter<'_, T, N> {
111 RingIter { ring: self, pos: 0 }
112 }
113}
114
115impl<T: Copy + Default, const N: usize> Default for RingBuf<T, N> {
116 fn default() -> Self {
117 Self::new()
118 }
119}
120
121impl<T: Copy + Default, const N: usize> core::fmt::Debug for RingBuf<T, N> {
122 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123 f.debug_struct("RingBuf")
124 .field("len", &self.len)
125 .field("capacity", &N)
126 .finish()
127 }
128}
129
130pub struct RingIter<'a, T: Copy + Default, const N: usize> {
132 ring: &'a RingBuf<T, N>,
133 pos: usize,
134}
135
136impl<'a, T: Copy + Default, const N: usize> Iterator for RingIter<'a, T, N> {
137 type Item = T;
138
139 fn next(&mut self) -> Option<T> {
140 let val = self.ring.get(self.pos)?;
141 self.pos += 1;
142 Some(val)
143 }
144
145 fn size_hint(&self) -> (usize, Option<usize>) {
146 let remaining = self.ring.len().saturating_sub(self.pos);
147 (remaining, Some(remaining))
148 }
149}
150
151impl<T: Copy + Default, const N: usize> ExactSizeIterator for RingIter<'_, T, N> {}
152
153impl<T: Copy + Default, const N: usize> core::fmt::Debug for RingIter<'_, T, N> {
154 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
155 f.debug_struct("RingIter")
156 .field("remaining", &(self.ring.len().saturating_sub(self.pos)))
157 .finish()
158 }
159}
160
161impl<'a, T: Copy + Default, const N: usize> IntoIterator for &'a RingBuf<T, N> {
162 type Item = T;
163 type IntoIter = RingIter<'a, T, N>;
164
165 fn into_iter(self) -> RingIter<'a, T, N> {
166 self.iter()
167 }
168}
169
170impl<T: Copy + Default, const N: usize> crate::traits::Sink<T> for RingBuf<T, N> {
171 type Error = core::convert::Infallible;
172
173 #[inline]
174 fn try_push(&mut self, val: T) -> Result<(), core::convert::Infallible> {
175 self.push(val);
176 Ok(())
177 }
178}
179
180#[cfg(test)]
181mod tests {
182 use super::*;
183
184 #[test]
185 fn new_ring_is_empty() {
186 let r = RingBuf::<u32, 4>::new();
187 assert!(r.is_empty());
188 assert!(!r.is_full());
189 assert_eq!(r.len(), 0);
190 assert_eq!(r.latest(), None);
191 assert_eq!(r.get(0), None);
192 }
193
194 #[test]
195 fn push_and_get() {
196 let mut r = RingBuf::<u32, 4>::new();
197 r.push(10);
198 r.push(20);
199 r.push(30);
200 assert_eq!(r.len(), 3);
201 assert_eq!(r.get(0), Some(10));
202 assert_eq!(r.get(1), Some(20));
203 assert_eq!(r.get(2), Some(30));
204 assert_eq!(r.get(3), None);
205 assert_eq!(r.latest(), Some(30));
206 }
207
208 #[test]
209 fn overwrite_oldest_when_full() {
210 let mut r = RingBuf::<u32, 3>::new();
211 r.push(1);
212 r.push(2);
213 r.push(3);
214 assert!(r.is_full());
215
216 r.push(4); assert_eq!(r.len(), 3);
218 assert_eq!(r.get(0), Some(2));
219 assert_eq!(r.get(1), Some(3));
220 assert_eq!(r.get(2), Some(4));
221 assert_eq!(r.latest(), Some(4));
222 }
223
224 #[test]
225 fn clear_resets_state() {
226 let mut r = RingBuf::<u32, 4>::new();
227 r.push(1);
228 r.push(2);
229 r.clear();
230 assert!(r.is_empty());
231 assert_eq!(r.len(), 0);
232 assert_eq!(r.latest(), None);
233 }
234
235 #[test]
236 fn iter_oldest_to_newest() {
237 let mut r = RingBuf::<u32, 4>::new();
238 for i in 1..=6 {
239 r.push(i);
240 }
241 let v: std::vec::Vec<u32> = r.iter().collect();
243 assert_eq!(v, [3, 4, 5, 6]);
244 }
245
246 #[test]
247 fn iter_exact_size() {
248 let mut r = RingBuf::<u32, 4>::new();
249 r.push(1);
250 r.push(2);
251 let it = r.iter();
252 assert_eq!(it.len(), 2);
253 }
254
255 #[test]
256 fn default_is_new() {
257 let r: RingBuf<u8, 8> = RingBuf::default();
258 assert!(r.is_empty());
259 }
260
261 #[test]
262 #[should_panic(expected = "RingBuf capacity N must be > 0")]
263 fn zero_capacity_panics() {
264 let _ = RingBuf::<u32, 0>::new();
265 }
266
267 #[test]
268 fn capacity_returns_n() {
269 let r = RingBuf::<u32, 8>::new();
270 assert_eq!(r.capacity(), 8);
271 }
272
273 #[test]
274 fn into_iter_for_ref() {
275 let mut r = RingBuf::<u32, 4>::new();
276 r.push(1);
277 r.push(2);
278 r.push(3);
279 let v: std::vec::Vec<u32> = (&r).into_iter().collect();
280 assert_eq!(v, [1, 2, 3]);
281 }
282}