detcore_model/collections/
replay_cursor.rs1use std::collections::VecDeque;
10use std::fmt;
11use std::iter::FromIterator;
12
13#[derive(Debug)]
18pub struct ReplayCursor<T> {
19 inner_data: VecDeque<T>,
20}
21
22impl<T: Eq + fmt::Display> ReplayCursor<T> {
23 pub fn peek_nth(&self, index: usize) -> Option<&T> {
25 self.inner_data.get(index)
26 }
27
28 pub fn peek(&self) -> Option<&T> {
30 self.peek_nth(0)
31 }
32
33 pub fn prefix_contains<F>(&self, winsize: usize, pred: F) -> Option<usize>
36 where
37 F: Fn(&T) -> bool,
38 {
39 for (i, v) in self.inner_data.iter().enumerate().take(winsize) {
40 if pred(v) {
41 return Some(i);
42 }
43 }
44 None
45 }
46
47 pub fn drop(&mut self, count: usize) {
48 let _ = self.inner_data.split_off(count);
49 }
50
51 pub fn display_first_n(&self, count: usize) -> String {
53 let mut acc = String::new();
54 let mut first = true;
55 for x in self.inner_data.iter().take(count) {
56 acc.push_str(&format!("{}{}", if first { "" } else { " " }, x));
57 first = false;
58 }
59 acc
60 }
61}
62
63impl<T> Iterator for ReplayCursor<T> {
64 type Item = T;
65
66 fn next(&mut self) -> Option<Self::Item> {
67 if self.inner_data.is_empty() {
68 None
69 } else {
70 self.inner_data.pop_front()
71 }
72 }
73}
74
75impl<T: fmt::Display> FromIterator<T> for ReplayCursor<T> {
76 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
77 let reverse_data: VecDeque<_> = VecDeque::from_iter(iter);
78 Self {
79 inner_data: reverse_data,
80 }
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use std::collections::VecDeque;
87 use std::fmt::Display;
88
89 use pretty_assertions::assert_eq;
90
91 use super::*;
92
93 fn peek_pair<T>(cursor: &ReplayCursor<T>) -> (Option<&T>, Option<&T>)
94 where
95 T: std::cmp::Eq + Display,
96 {
97 (cursor.peek_nth(0), cursor.peek_nth(1))
98 }
99
100 #[test]
101 fn test_peek() {
102 let cursor: ReplayCursor<usize> = vec![1, 2, 3, 4, 5, 6].into_iter().collect();
103 assert_eq!(cursor.peek(), Some(&1));
104 }
105
106 #[test]
107 fn test_peek_empty() {
108 let cursor = ReplayCursor::<usize> {
109 inner_data: VecDeque::new(),
110 };
111 assert_eq!(cursor.peek(), None);
112 }
113
114 #[test]
115 fn test_peek_pair() {
116 let cursor: ReplayCursor<usize> = vec![1, 2, 3].into_iter().collect();
117 assert_eq!(peek_pair(&cursor), (Some(&1), Some(&2)));
118 assert_eq!(peek_pair(&cursor), (Some(&1), Some(&2)));
119 }
120
121 #[test]
122 fn test_peek_pair_one() {
123 let cursor: ReplayCursor<usize> = vec![1].into_iter().collect();
124 assert_eq!(peek_pair(&cursor), (Some(&1), None));
125 assert_eq!(peek_pair(&cursor), (Some(&1), None));
126 }
127
128 #[test]
129 fn test_peek_pair_empty() {
130 let cursor: ReplayCursor<usize> = ReplayCursor {
131 inner_data: VecDeque::new(),
132 };
133 assert_eq!(peek_pair(&cursor), (None, None));
134 assert_eq!(peek_pair(&cursor), (None, None));
135 }
136
137 #[test]
138 fn test_next() {
139 let mut cursor: ReplayCursor<usize> = vec![1, 2, 3].into_iter().collect();
140 let result = vec![cursor.next(), cursor.next(), cursor.next(), cursor.next()];
141 assert_eq!(result, vec![Some(1), Some(2), Some(3), None]);
142 }
143
144 #[test]
145 fn test_peek_nth() {
146 let cursor: ReplayCursor<usize> = vec![1, 2, 3].into_iter().collect();
147 let result = vec![
148 cursor.peek_nth(0),
149 cursor.peek_nth(1),
150 cursor.peek_nth(2),
151 cursor.peek_nth(3),
152 ];
153 assert_eq!(result, vec![Some(&1), Some(&2), Some(&3), None]);
154 }
155}