summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ast_pretty/src/pp/ring.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ast_pretty/src/pp/ring.rs')
-rw-r--r--compiler/rustc_ast_pretty/src/pp/ring.rs77
1 files changed, 77 insertions, 0 deletions
diff --git a/compiler/rustc_ast_pretty/src/pp/ring.rs b/compiler/rustc_ast_pretty/src/pp/ring.rs
new file mode 100644
index 000000000..8187394fe
--- /dev/null
+++ b/compiler/rustc_ast_pretty/src/pp/ring.rs
@@ -0,0 +1,77 @@
+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<T> {
+ data: VecDeque<T>,
+ // Abstract index of data[0] in the infinitely sized queue.
+ offset: usize,
+}
+
+impl<T> RingBuffer<T> {
+ 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<T> {
+ 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<T> Index<usize> for RingBuffer<T> {
+ type Output = T;
+ fn index(&self, index: usize) -> &Self::Output {
+ &self.data[index.checked_sub(self.offset).unwrap()]
+ }
+}
+
+impl<T> IndexMut<usize> for RingBuffer<T> {
+ fn index_mut(&mut self, index: usize) -> &mut Self::Output {
+ &mut self.data[index.checked_sub(self.offset).unwrap()]
+ }
+}