/
history.rs
86 lines (74 loc) · 2.32 KB
/
history.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::collections::VecDeque;
/// Trait for history handling.
pub trait History<T> {
/// This is called with the current position that should
/// be read from history. The `pos` represents the number
/// of times the `Up`/`Down` arrow key has been pressed.
/// This would normally be used as an index to some sort
/// of vector. If the `pos` does not have an entry, [`None`](Option::None)
/// should be returned.
fn read(&self, pos: usize) -> Option<String>;
/// This is called with the next value you should store
/// in history at the first location. Normally history
/// is implemented as a FIFO queue.
fn write(&mut self, val: &T);
}
pub struct BasicHistory {
max_entries: Option<usize>,
deque: VecDeque<String>,
no_duplicates: bool,
}
impl BasicHistory {
/// Creates a new basic history value which has no limit on the number of
/// entries and allows for duplicates.
///
/// # Example
///
/// A history with at most 8 entries and no duplicates:
///
/// ```rs
/// let mut history = BasicHistory::new().max_entries(8).no_duplicates(true);
/// ```
pub fn new() -> Self {
Self {
max_entries: None,
deque: VecDeque::new(),
no_duplicates: false,
}
}
/// Limit the number of entries stored in the history.
pub fn max_entries(self, max_entries: usize) -> Self {
Self {
max_entries: Some(max_entries),
..self
}
}
/// Prevent duplicates in the history. This means that any previous entries
/// that are equal to a new entry are removed before the new entry is added.
pub fn no_duplicates(self, no_duplicates: bool) -> Self {
Self {
no_duplicates,
..self
}
}
}
impl<T: ToString> History<T> for BasicHistory {
fn read(&self, pos: usize) -> Option<String> {
self.deque.get(pos).cloned()
}
fn write(&mut self, val: &T) {
let val = val.to_string();
if self.no_duplicates {
self.deque.retain(|v| v != &val);
}
self.deque.push_front(val);
if let Some(max_entries) = self.max_entries {
self.deque.truncate(max_entries);
}
}
}
impl Default for BasicHistory {
fn default() -> Self {
Self::new()
}
}