1use std::{
2 collections::{BTreeMap, HashMap},
3 sync::Arc,
4};
5
6#[derive(Debug, Clone, PartialEq)]
7pub struct RollingSet<T: std::hash::Hash + std::cmp::Eq> {
8 value_identifyer: usize,
9 capacity: usize,
10 time_to_value: BTreeMap<usize, Arc<T>>,
11 value_to_time: HashMap<Arc<T>, usize>,
12}
13
14impl<T> RollingSet<T>
15where
16 T: Eq + std::hash::Hash + Clone,
17{
18 pub fn new(capacity: usize) -> Self {
19 Self {
20 capacity,
21 value_identifyer: 0,
22 time_to_value: BTreeMap::new(),
23 value_to_time: HashMap::new(),
24 }
25 }
26
27 pub fn with_capacity(capacity: usize) -> Self {
28 Self {
29 capacity,
30 value_identifyer: 0,
31 time_to_value: BTreeMap::new(),
32
33 value_to_time: HashMap::with_capacity(capacity),
34 }
35 }
36
37 pub fn insert(&mut self, element: T) {
38 self.value_identifyer += 1;
39 let v = Arc::new(element);
40 self.time_to_value.insert(self.value_identifyer, v.clone());
41 self.value_to_time.insert(v, self.value_identifyer);
43
44 if self.len() > self.capacity {
45 self.pop();
46 }
47 }
48
49 pub fn pop(&mut self) -> Option<T> {
50 let first = self.time_to_value.first_key_value()?.0.clone();
52 let value = self.time_to_value.get(&first)?.clone();
53 self.value_to_time.remove(&value);
54 self.time_to_value.remove(&first);
55 if !self.is_empty() {
56 self.value_identifyer = 0;
57 }
58 Some((*value).clone())
59 }
60
61 pub fn is_empty(&self) -> bool {
62 self.len() == 0
63 }
64
65 pub fn is_full(&self) -> bool {
66 self.len() == self.capacity
67 }
68
69 pub fn set_capacity(&mut self, new: usize) -> usize {
70 self.capacity = new;
71 self.capacity
72 }
73
74 pub fn capacity(&self) -> usize {
75 self.capacity
76 }
77
78 pub fn remove(&mut self, element: &T) -> bool {
79 let i = match self.value_to_time.get(element) {
80 Some(i) => i,
81 None => return false,
82 };
83
84 self.time_to_value.remove(i);
85 self.value_to_time.remove(element);
86 true
87 }
88
89 pub fn contains(&self, element: &T) -> bool {
90 self.value_to_time.contains_key(element)
91 }
92
93 pub fn len(&self) -> usize {
94 self.value_to_time.len()
95 }
96
97 pub fn clear(&mut self) {
98 self.value_identifyer = 0;
99 self.time_to_value.clear();
100 self.value_to_time.clear();
101 }
102}
103
104#[cfg(test)]
105mod tests {
106
107 use crate::RollingSet;
108
109 #[test]
110 fn create() {
111 let mut set = RollingSet::new(100);
112 set.insert("one");
113 set.insert("two");
114 set.insert("three");
115
116 assert!(set.contains(&"one"));
117 assert!(set.contains(&"two"));
118 assert!(set.contains(&"three"));
119 assert!(!set.contains(&"four"));
120 }
121
122 #[test]
123 fn roll() {
124 let mut set = RollingSet::new(3);
125 set.insert("one");
126 set.insert("two");
127 set.insert("three");
128 set.insert("four");
130 assert_eq!(set.len(), 3);
131 assert!(!set.contains(&"one"));
132 assert!(set.contains(&"two"));
133 assert!(set.contains(&"three"));
134 assert!(set.contains(&"four"));
135 }
136
137 #[test]
138 fn remove() {
139 let mut set = RollingSet::new(3);
140 set.insert("one");
141 set.insert("two");
142 set.insert("three");
143 set.insert("four");
144
145 assert!(set.contains(&"two"));
146 assert!(set.contains(&"three"));
147 assert!(set.contains(&"four"));
148
149 set.remove(&"two");
150 assert_eq!(set.len(), 2);
151 assert!(!set.contains(&"two"));
152 assert!(set.contains(&"three"));
153 assert!(set.contains(&"four"));
154 }
155
156 #[test]
157 fn len() {
158 let mut set = RollingSet::new(3);
159 set.insert("one");
160 set.insert("two");
161 set.insert("three");
162 assert_eq!(set.len(), 3);
163 set.insert("four");
164
165 assert_eq!(set.len(), 3);
167
168 assert!(set.contains(&"two"));
169 assert!(set.contains(&"three"));
170 assert!(set.contains(&"four"));
171
172 set.remove(&"two");
173 assert_eq!(set.len(), 2);
174 assert!(!set.contains(&"two"));
175 assert!(set.contains(&"three"));
176 assert!(set.contains(&"four"));
177 }
178
179 #[test]
180 fn pop() {
181 let mut set = RollingSet::new(3);
182 set.insert("one");
183 set.insert("two");
184 set.insert("three");
185 assert_eq!(set.len(), 3);
186
187 let value = set.pop();
188 assert_eq!(value, Some("one"));
189 assert_eq!(set.len(), 2);
190
191 let value = set.pop();
192 assert_eq!(value, Some("two"));
193 assert_eq!(set.len(), 1);
194
195 let value = set.pop();
196 assert_eq!(value, Some("three"));
197 assert_eq!(set.len(), 0);
198
199 set.insert("one");
200 set.insert("two");
201 set.insert("three");
202 set.insert("four");
203 assert_eq!(set.len(), 3);
204
205 let value = set.pop();
206 assert_eq!(value, Some("two"));
207 assert_eq!(set.len(), 2);
208
209 let value = set.pop();
210 assert_eq!(value, Some("three"));
211 assert_eq!(set.len(), 1);
212
213 let value = set.pop();
214 assert_eq!(value, Some("four"));
215 assert_eq!(set.len(), 0);
216 }
217
218 #[test]
219 fn iter() {
220 let mut set = RollingSet::new(3);
221 set.insert("one");
222 set.insert("two");
223 set.insert("three");
224 }
225}