cli/util/
ring_buffer.rs

1/*---------------------------------------------------------------------------------------------
2 *  Copyright (c) Microsoft Corporation. All rights reserved.
3 *  Licensed under the MIT License. See License.txt in the project root for license information.
4 *--------------------------------------------------------------------------------------------*/
5
6pub struct RingBuffer<T> {
7	data: Vec<T>,
8	i: usize,
9}
10
11impl<T> RingBuffer<T> {
12	pub fn new(capacity: usize) -> Self {
13		Self {
14			data: Vec::with_capacity(capacity),
15			i: 0,
16		}
17	}
18
19	pub fn capacity(&self) -> usize {
20		self.data.capacity()
21	}
22
23	pub fn len(&self) -> usize {
24		self.data.len()
25	}
26
27	pub fn is_full(&self) -> bool {
28		self.data.len() == self.data.capacity()
29	}
30
31	pub fn is_empty(&self) -> bool {
32		self.data.len() == 0
33	}
34
35	pub fn push(&mut self, value: T) {
36		if self.data.len() == self.data.capacity() {
37			self.data[self.i] = value;
38		} else {
39			self.data.push(value);
40		}
41
42		self.i = (self.i + 1) % self.data.capacity();
43	}
44
45	pub fn iter(&self) -> RingBufferIter<'_, T> {
46		RingBufferIter {
47			index: 0,
48			buffer: self,
49		}
50	}
51}
52
53impl<T: Default> IntoIterator for RingBuffer<T> {
54	type Item = T;
55	type IntoIter = OwnedRingBufferIter<T>;
56
57	fn into_iter(self) -> OwnedRingBufferIter<T>
58	where
59		T: Default,
60	{
61		OwnedRingBufferIter {
62			index: 0,
63			buffer: self,
64		}
65	}
66}
67
68pub struct OwnedRingBufferIter<T: Default> {
69	buffer: RingBuffer<T>,
70	index: usize,
71}
72
73impl<T: Default> Iterator for OwnedRingBufferIter<T> {
74	type Item = T;
75
76	fn next(&mut self) -> Option<Self::Item> {
77		if self.index == self.buffer.len() {
78			return None;
79		}
80
81		let ii = (self.index + self.buffer.i) % self.buffer.len();
82		let item = std::mem::take(&mut self.buffer.data[ii]);
83		self.index += 1;
84		Some(item)
85	}
86}
87
88pub struct RingBufferIter<'a, T> {
89	buffer: &'a RingBuffer<T>,
90	index: usize,
91}
92
93impl<'a, T> Iterator for RingBufferIter<'a, T> {
94	type Item = &'a T;
95
96	fn next(&mut self) -> Option<Self::Item> {
97		if self.index == self.buffer.len() {
98			return None;
99		}
100
101		let ii = (self.index + self.buffer.i) % self.buffer.len();
102		let item = &self.buffer.data[ii];
103		self.index += 1;
104		Some(item)
105	}
106}
107
108#[cfg(test)]
109mod tests {
110	use super::*;
111
112	#[test]
113	fn test_inserts() {
114		let mut rb = RingBuffer::new(3);
115		assert_eq!(rb.capacity(), 3);
116		assert!(!rb.is_full());
117		assert_eq!(rb.len(), 0);
118		assert_eq!(rb.iter().copied().count(), 0);
119
120		rb.push(1);
121		assert!(!rb.is_full());
122		assert_eq!(rb.len(), 1);
123		assert_eq!(rb.iter().copied().collect::<Vec<i32>>(), vec![1]);
124
125		rb.push(2);
126		assert!(!rb.is_full());
127		assert_eq!(rb.len(), 2);
128		assert_eq!(rb.iter().copied().collect::<Vec<i32>>(), vec![1, 2]);
129
130		rb.push(3);
131		assert!(rb.is_full());
132		assert_eq!(rb.len(), 3);
133		assert_eq!(rb.iter().copied().collect::<Vec<i32>>(), vec![1, 2, 3]);
134
135		rb.push(4);
136		assert!(rb.is_full());
137		assert_eq!(rb.len(), 3);
138		assert_eq!(rb.iter().copied().collect::<Vec<i32>>(), vec![2, 3, 4]);
139
140		assert_eq!(rb.into_iter().collect::<Vec<i32>>(), vec![2, 3, 4]);
141	}
142}