use std::collections::VecDeque;
use std::fmt;
use std::iter::FromIterator;
#[derive(Debug)]
pub struct ReplayCursor<T> {
inner_data: VecDeque<T>,
}
impl<T: Eq + fmt::Display> ReplayCursor<T> {
pub fn peek_nth(&self, index: usize) -> Option<&T> {
self.inner_data.get(index)
}
pub fn peek(&self) -> Option<&T> {
self.peek_nth(0)
}
pub fn prefix_contains<F>(&self, winsize: usize, pred: F) -> Option<usize>
where
F: Fn(&T) -> bool,
{
for (i, v) in self.inner_data.iter().enumerate().take(winsize) {
if pred(v) {
return Some(i);
}
}
None
}
pub fn drop(&mut self, count: usize) {
let _ = self.inner_data.split_off(count);
}
pub fn display_first_n(&self, count: usize) -> String {
let mut acc = String::new();
let mut first = true;
for x in self.inner_data.iter().take(count) {
acc.push_str(&format!("{}{}", if first { "" } else { " " }, x));
first = false;
}
acc
}
}
impl<T> Iterator for ReplayCursor<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.inner_data.is_empty() {
None
} else {
self.inner_data.pop_front()
}
}
}
impl<T: fmt::Display> FromIterator<T> for ReplayCursor<T> {
fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
let reverse_data: VecDeque<_> = VecDeque::from_iter(iter);
Self {
inner_data: reverse_data,
}
}
}
#[cfg(test)]
mod tests {
use std::collections::VecDeque;
use std::fmt::Display;
use pretty_assertions::assert_eq;
use super::*;
fn peek_pair<T>(cursor: &ReplayCursor<T>) -> (Option<&T>, Option<&T>)
where
T: std::cmp::Eq + Display,
{
(cursor.peek_nth(0), cursor.peek_nth(1))
}
#[test]
fn test_peek() {
let cursor: ReplayCursor<usize> = vec![1, 2, 3, 4, 5, 6].into_iter().collect();
assert_eq!(cursor.peek(), Some(&1));
}
#[test]
fn test_peek_empty() {
let cursor = ReplayCursor::<usize> {
inner_data: VecDeque::new(),
};
assert_eq!(cursor.peek(), None);
}
#[test]
fn test_peek_pair() {
let cursor: ReplayCursor<usize> = vec![1, 2, 3].into_iter().collect();
assert_eq!(peek_pair(&cursor), (Some(&1), Some(&2)));
assert_eq!(peek_pair(&cursor), (Some(&1), Some(&2)));
}
#[test]
fn test_peek_pair_one() {
let cursor: ReplayCursor<usize> = vec![1].into_iter().collect();
assert_eq!(peek_pair(&cursor), (Some(&1), None));
assert_eq!(peek_pair(&cursor), (Some(&1), None));
}
#[test]
fn test_peek_pair_empty() {
let cursor: ReplayCursor<usize> = ReplayCursor {
inner_data: VecDeque::new(),
};
assert_eq!(peek_pair(&cursor), (None, None));
assert_eq!(peek_pair(&cursor), (None, None));
}
#[test]
fn test_next() {
let mut cursor: ReplayCursor<usize> = vec![1, 2, 3].into_iter().collect();
let result = vec![cursor.next(), cursor.next(), cursor.next(), cursor.next()];
assert_eq!(result, vec![Some(1), Some(2), Some(3), None]);
}
#[test]
fn test_peek_nth() {
let cursor: ReplayCursor<usize> = vec![1, 2, 3].into_iter().collect();
let result = vec![
cursor.peek_nth(0),
cursor.peek_nth(1),
cursor.peek_nth(2),
cursor.peek_nth(3),
];
assert_eq!(result, vec![Some(&1), Some(&2), Some(&3), None]);
}
}