use std::collections::VecDeque; use std::ops::{Index, IndexMut}; /// A view onto a finite range of an infinitely long sequence of T. /// /// The Ts are indexed 0..infinity. A RingBuffer begins as a view of elements /// 0..0 (i.e. nothing). The user of the RingBuffer advances its left and right /// position independently, although only in the positive direction, and only /// with left <= right at all times. /// /// Holding a RingBuffer whose view is elements left..right gives the ability to /// use Index and IndexMut to access elements i in the infinitely long queue for /// which left <= i < right. pub struct RingBuffer { data: VecDeque, // Abstract index of data[0] in the infinitely sized queue. offset: usize, } impl RingBuffer { pub fn new() -> Self { RingBuffer { data: VecDeque::new(), offset: 0 } } pub fn is_empty(&self) -> bool { self.data.is_empty() } pub fn push(&mut self, value: T) -> usize { let index = self.offset + self.data.len(); self.data.push_back(value); index } pub fn clear(&mut self) { self.data.clear(); } pub fn index_of_first(&self) -> usize { self.offset } pub fn first(&self) -> Option<&T> { self.data.front() } pub fn first_mut(&mut self) -> Option<&mut T> { self.data.front_mut() } pub fn pop_first(&mut self) -> Option { let first = self.data.pop_front()?; self.offset += 1; Some(first) } pub fn last(&self) -> Option<&T> { self.data.back() } pub fn last_mut(&mut self) -> Option<&mut T> { self.data.back_mut() } } impl Index for RingBuffer { type Output = T; fn index(&self, index: usize) -> &Self::Output { &self.data[index.checked_sub(self.offset).unwrap()] } } impl IndexMut for RingBuffer { fn index_mut(&mut self, index: usize) -> &mut Self::Output { &mut self.data[index.checked_sub(self.offset).unwrap()] } }