1use std::{
16 collections::{
17 VecDeque,
18 vec_deque::{Drain, Iter, IterMut},
19 },
20 num::NonZeroUsize,
21 ops::RangeBounds,
22};
23
24use serde::{Deserialize, Deserializer, Serialize};
25
26const LEGACY_DEFAULT_CAPACITY: NonZeroUsize = NonZeroUsize::new(10).unwrap();
29
30#[derive(Clone, Debug, PartialEq, Serialize)]
36pub struct RingBuffer<T> {
37 #[serde(rename = "items")]
38 inner: VecDeque<T>,
39
40 capacity: NonZeroUsize,
43}
44
45impl<T> RingBuffer<T> {
46 fn from_parts(mut inner: VecDeque<T>, capacity: NonZeroUsize) -> Self {
47 let capacity_as_usize = capacity.get();
48
49 for _ in capacity_as_usize..inner.len() {
50 inner.pop_front();
51 }
52
53 if let Some(extra_space) = capacity_as_usize.checked_sub(inner.len()) {
54 inner.reserve_exact(extra_space);
55 }
56
57 Self { inner, capacity }
58 }
59
60 pub fn new(size: NonZeroUsize) -> Self {
63 Self::from_parts(VecDeque::with_capacity(size.into()), size)
64 }
65
66 pub fn len(&self) -> usize {
71 self.inner.len()
72 }
73
74 pub fn is_empty(&self) -> bool {
76 self.inner.is_empty()
77 }
78
79 pub fn get(&self, index: usize) -> Option<&T> {
84 self.inner.get(index)
85 }
86
87 pub fn push(&mut self, value: T) {
90 if self.inner.len() == self.inner.capacity() {
91 self.inner.pop_front();
92 }
93
94 self.inner.push_back(value);
95 }
96
97 pub fn pop(&mut self) -> Option<T> {
100 self.inner.pop_front()
101 }
102
103 pub fn remove(&mut self, index: usize) -> Option<T> {
106 self.inner.remove(index)
107 }
108
109 pub fn iter(&self) -> Iter<'_, T> {
112 self.inner.iter()
113 }
114
115 pub fn iter_mut(&mut self) -> IterMut<'_, T> {
119 self.inner.iter_mut()
120 }
121
122 pub fn drain<R>(&mut self, range: R) -> Drain<'_, T>
124 where
125 R: RangeBounds<usize>,
126 {
127 self.inner.drain(range)
128 }
129
130 pub fn clear(&mut self) {
133 self.inner.clear();
134 }
135
136 pub fn capacity(&self) -> usize {
138 self.inner.capacity()
139 }
140
141 pub fn retain<F>(&mut self, predicate: F)
143 where
144 F: FnMut(&T) -> bool,
145 {
146 self.inner.retain(predicate)
147 }
148}
149
150impl<'a, T: Deserialize<'a>> Deserialize<'a> for RingBuffer<T> {
153 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
154 where
155 D: Deserializer<'a>,
156 {
157 #[derive(Deserialize)]
158 #[serde(untagged)]
159 enum SerializedRingBuffer<T> {
160 WithCapacity { items: VecDeque<T>, capacity: NonZeroUsize },
161 Legacy(VecDeque<T>),
162 }
163
164 match SerializedRingBuffer::deserialize(deserializer)? {
165 SerializedRingBuffer::WithCapacity { items, capacity } => {
166 Ok(Self::from_parts(items, capacity))
167 }
168 SerializedRingBuffer::Legacy(items) => {
169 let capacity = NonZeroUsize::new(items.len().max(LEGACY_DEFAULT_CAPACITY.get()))
170 .expect("legacy capacity is non-zero");
171 Ok(Self::from_parts(items, capacity))
172 }
173 }
174 }
175}
176
177impl<U> Extend<U> for RingBuffer<U> {
178 fn extend<T: IntoIterator<Item = U>>(&mut self, iter: T) {
179 for item in iter.into_iter() {
180 self.push(item);
181 }
182 }
183}
184
185#[cfg(test)]
186mod tests {
187 use std::{num::NonZeroUsize, ops::Not};
188
189 use super::RingBuffer;
190
191 #[test]
192 pub fn test_fixed_size() {
193 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(5).unwrap());
194
195 assert!(ring_buffer.is_empty());
196
197 ring_buffer.push(1);
198 ring_buffer.push(2);
199 ring_buffer.push(3);
200
201 assert!(ring_buffer.is_empty().not());
202
203 assert_eq!(ring_buffer.get(0), Some(&1));
204 assert_eq!(ring_buffer.get(1), Some(&2));
205 assert_eq!(ring_buffer.get(2), Some(&3));
206
207 ring_buffer.push(4);
208 ring_buffer.push(5);
209
210 assert_eq!(ring_buffer.get(0), Some(&1));
211 assert_eq!(ring_buffer.get(1), Some(&2));
212 assert_eq!(ring_buffer.get(2), Some(&3));
213 assert_eq!(ring_buffer.get(3), Some(&4));
214 assert_eq!(ring_buffer.get(4), Some(&5));
215
216 ring_buffer.push(6);
217
218 assert_eq!(ring_buffer.get(0), Some(&2));
219 assert_eq!(ring_buffer.get(1), Some(&3));
220 assert_eq!(ring_buffer.get(2), Some(&4));
221 assert_eq!(ring_buffer.get(3), Some(&5));
222 assert_eq!(ring_buffer.get(4), Some(&6));
223 }
224
225 #[test]
226 pub fn test_push_and_pop_and_remove_and_length() {
227 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(3).unwrap());
228
229 ring_buffer.push(1);
230 assert_eq!(ring_buffer.len(), 1);
231
232 ring_buffer.push(2);
233 assert_eq!(ring_buffer.len(), 2);
234
235 ring_buffer.push(3);
236 assert_eq!(ring_buffer.len(), 3);
237
238 assert_eq!(ring_buffer.pop(), Some(1));
239 assert_eq!(ring_buffer.len(), 2);
240 assert_eq!(ring_buffer.get(0), Some(&2));
241 assert_eq!(ring_buffer.get(1), Some(&3));
242 assert_eq!(ring_buffer.get(2), None);
243
244 assert_eq!(ring_buffer.pop(), Some(2));
245 assert_eq!(ring_buffer.len(), 1);
246 assert_eq!(ring_buffer.get(0), Some(&3));
247 assert_eq!(ring_buffer.get(1), None);
248 assert_eq!(ring_buffer.get(2), None);
249
250 assert_eq!(ring_buffer.pop(), Some(3));
251 assert_eq!(ring_buffer.len(), 0);
252 assert_eq!(ring_buffer.get(0), None);
253 assert_eq!(ring_buffer.get(1), None);
254 assert_eq!(ring_buffer.get(2), None);
255
256 assert_eq!(ring_buffer.pop(), None);
257
258 ring_buffer.push(1);
259 ring_buffer.push(2);
260 ring_buffer.push(3);
261 assert_eq!(ring_buffer.len(), 3);
262 assert_eq!(ring_buffer.get(0), Some(&1));
263 assert_eq!(ring_buffer.get(1), Some(&2));
264 assert_eq!(ring_buffer.get(2), Some(&3));
265
266 assert_eq!(ring_buffer.remove(1), Some(2));
267 assert_eq!(ring_buffer.len(), 2);
268 assert_eq!(ring_buffer.get(0), Some(&1));
269 assert_eq!(ring_buffer.get(1), Some(&3));
270 assert_eq!(ring_buffer.get(2), None);
271
272 assert_eq!(ring_buffer.remove(0), Some(1));
273 assert_eq!(ring_buffer.len(), 1);
274 assert_eq!(ring_buffer.get(0), Some(&3));
275 assert_eq!(ring_buffer.get(1), None);
276 assert_eq!(ring_buffer.get(2), None);
277
278 assert_eq!(ring_buffer.remove(1), None);
279 assert_eq!(ring_buffer.remove(10), None);
280 }
281
282 #[test]
283 fn test_iter() {
284 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(5).unwrap());
285
286 ring_buffer.push(1);
287 ring_buffer.push(2);
288 ring_buffer.push(3);
289
290 let as_vec = ring_buffer.iter().copied().collect::<Vec<_>>();
291 assert_eq!(as_vec, [1, 2, 3]);
292
293 let first_entry = ring_buffer.iter_mut().next().unwrap();
294 *first_entry = 42;
295
296 let as_vec = ring_buffer.iter().copied().collect::<Vec<_>>();
297 assert_eq!(as_vec, [42, 2, 3]);
298 }
299
300 #[test]
301 fn test_drain() {
302 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(5).unwrap());
303
304 ring_buffer.push(1);
305 ring_buffer.push(2);
306 ring_buffer.push(3);
307 ring_buffer.push(4);
308 ring_buffer.push(5);
309
310 let drained = ring_buffer.drain(0..=2).collect::<Vec<_>>();
311 let left = ring_buffer.iter().map(ToOwned::to_owned).collect::<Vec<_>>();
312
313 assert_eq!(drained, &[1, 2, 3]);
314 assert_eq!(left, &[4, 5]);
315
316 ring_buffer.drain(..);
317
318 assert!(ring_buffer.is_empty());
319 }
320
321 #[test]
322 fn test_clear_on_empty_buffer_is_a_noop() {
323 let mut ring_buffer: RingBuffer<u8> = RingBuffer::new(NonZeroUsize::new(3).unwrap());
324 ring_buffer.clear();
325 assert_eq!(ring_buffer.len(), 0);
326 }
327
328 #[test]
329 fn test_clear_removes_all_items() {
330 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(3).unwrap());
332 ring_buffer.push(4);
333 ring_buffer.push(5);
334 ring_buffer.push(6);
335 ring_buffer.pop();
336 assert_eq!(ring_buffer.len(), 2);
338
339 ring_buffer.clear();
341
342 assert_eq!(ring_buffer.len(), 0);
344 assert_eq!(ring_buffer.get(0), None);
345 assert_eq!(ring_buffer.pop(), None);
346 }
347
348 #[test]
349 fn test_clear_does_not_affect_capacity() {
350 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(3).unwrap());
352 ring_buffer.push(4);
353 ring_buffer.push(5);
354 ring_buffer.push(6);
355 ring_buffer.pop();
356 assert_eq!(ring_buffer.capacity(), 3);
358
359 ring_buffer.clear();
361
362 assert_eq!(ring_buffer.capacity(), 3);
364 }
365
366 #[test]
367 fn test_capacity_is_what_we_passed_to_new() {
368 let ring_buffer = RingBuffer::<i32>::new(NonZeroUsize::new(13).unwrap());
370 assert_eq!(ring_buffer.capacity(), 13);
372 }
373
374 #[test]
375 fn test_capacity_is_not_affected_by_overflowing() {
376 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(3).unwrap());
378 ring_buffer.push(4);
379 ring_buffer.push(5);
380 ring_buffer.push(6);
381 ring_buffer.push(7);
382 ring_buffer.pop();
383 ring_buffer.push(8);
384 ring_buffer.push(9);
385
386 assert_eq!(ring_buffer.capacity(), 3);
388
389 ring_buffer.extend(vec![10, 11, 12, 13, 14, 15]);
391
392 assert_eq!(ring_buffer.capacity(), 3);
394 }
395
396 #[test]
397 fn test_roundtrip_serialization() {
398 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(3).unwrap());
400 ring_buffer.push("1".to_owned());
401 ring_buffer.push("2".to_owned());
402
403 let json = serde_json::to_string(&ring_buffer).expect("serialisation failed");
405 assert_eq!(json, r#"{"items":["1","2"],"capacity":3}"#);
407
408 let new_ring_buffer: RingBuffer<String> =
410 serde_json::from_str(&json).expect("deserialisation failed");
411
412 assert_eq!(ring_buffer, new_ring_buffer);
414 assert_eq!(new_ring_buffer.capacity(), 3);
415 assert_eq!(new_ring_buffer.inner.capacity(), 3);
416 }
417
418 #[test]
419 fn test_deserializes_the_legacy_sequence_format() {
420 let mut ring_buffer: RingBuffer<i32> = serde_json::from_str("[1,2]").unwrap();
421
422 assert_eq!(ring_buffer.iter().copied().collect::<Vec<_>>(), vec![1, 2]);
423 assert_eq!(ring_buffer.capacity(), 10);
424 assert_eq!(ring_buffer.inner.capacity(), 10);
425
426 ring_buffer.push(3);
428 assert_eq!(ring_buffer.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3]);
429 }
430
431 #[test]
432 fn test_extending_an_empty_ringbuffer_adds_the_items() {
433 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(5).unwrap());
435
436 ring_buffer.extend(vec!["a".to_owned(), "b".to_owned()]);
438
439 assert_eq!(ring_buffer.iter().map(String::as_str).collect::<Vec<_>>(), vec!["a", "b"]);
441 }
442
443 #[test]
444 fn test_extend_adds_items_to_the_end() {
445 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(5).unwrap());
447 ring_buffer.push("1".to_owned());
448 ring_buffer.push("2".to_owned());
449
450 ring_buffer.extend(vec!["3".to_owned(), "4".to_owned()]);
452
453 assert_eq!(
455 ring_buffer.iter().map(String::as_str).collect::<Vec<_>>(),
456 vec!["1", "2", "3", "4"]
457 );
458 }
459
460 #[test]
461 fn test_extend_does_not_overflow_max_length() {
462 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(5).unwrap());
464 ring_buffer.push("1".to_owned());
465 ring_buffer.push("2".to_owned());
466
467 ring_buffer.extend(vec![
469 "3".to_owned(),
470 "4".to_owned(),
471 "5".to_owned(),
472 "6".to_owned(),
473 "7".to_owned(),
474 ]);
475
476 assert_eq!(
478 ring_buffer.iter().map(String::as_str).collect::<Vec<_>>(),
479 vec!["3", "4", "5", "6", "7"]
480 );
481 }
482
483 #[test]
484 fn test_extending_a_full_ringbuffer_preserves_max_length() {
485 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(2).unwrap());
487 ring_buffer.push("1".to_owned());
488 ring_buffer.push("2".to_owned());
489
490 ring_buffer.extend(vec![
492 "3".to_owned(),
493 "4".to_owned(),
494 "5".to_owned(),
495 "6".to_owned(),
496 "7".to_owned(),
497 ]);
498
499 assert_eq!(ring_buffer.iter().map(String::as_str).collect::<Vec<_>>(), vec!["6", "7"]);
501 }
502
503 #[test]
504 fn test_capacity_survives_a_serialization_round_trip() {
505 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(3).unwrap());
507 ring_buffer.push(1);
508
509 let json = serde_json::to_string(&ring_buffer).unwrap();
511 let mut ring_buffer: RingBuffer<i32> = serde_json::from_str(&json).unwrap();
512
513 assert_eq!(ring_buffer.capacity(), 3);
515 assert_eq!(ring_buffer.inner.capacity(), 3);
516 ring_buffer.push(2);
517 ring_buffer.push(3);
518
519 assert_eq!(ring_buffer.iter().copied().collect::<Vec<_>>(), vec![1, 2, 3]);
520 }
521
522 #[test]
523 fn test_retain() {
524 let mut ring_buffer = RingBuffer::new(NonZeroUsize::new(2).unwrap());
525 ring_buffer.push(1);
526 ring_buffer.push(2);
527
528 ring_buffer.retain(|v| v % 2 == 0);
529
530 assert_eq!(ring_buffer.len(), 1);
531 assert_eq!(ring_buffer.get(0).copied().unwrap(), 2);
532 }
533}