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