1pub struct UsingQueue<T> {
23 pending: Option<T>,
25 in_use: Vec<T>,
27 max_size: usize,
29}
30
31pub enum GetAction {
33 Take,
35 Clone,
37}
38
39impl<T> UsingQueue<T> {
40 pub fn new(max_size: usize) -> UsingQueue<T> {
42 UsingQueue {
43 pending: None,
44 in_use: vec![],
45 max_size,
46 }
47 }
48
49 pub fn peek_last_ref(&self) -> Option<&T> {
52 self.pending.as_ref().or(self.in_use.last())
53 }
54
55 pub fn use_last_ref(&mut self) -> Option<&T> {
59 if let Some(x) = self.pending.take() {
60 self.in_use.push(x);
61 if self.in_use.len() > self.max_size {
62 self.in_use.remove(0);
63 }
64 }
65 self.in_use.last()
66 }
67
68 pub fn set_pending(&mut self, b: T) {
71 self.pending = Some(b);
72 }
73
74 pub fn is_in_use(&self) -> bool { self.in_use.len() > 0 }
76
77 pub fn reset(&mut self) {
79 self.pending = None;
80 self.in_use.clear();
81 }
82
83 fn take_used_if<P>(&mut self, predicate: P) -> Option<T> where P: Fn(&T) -> bool {
86 self.in_use.iter().position(|r| predicate(r)).map(|i| self.in_use.remove(i))
87 }
88
89 fn clone_used_if<P>(&mut self, predicate: P) -> Option<T> where P: Fn(&T) -> bool, T: Clone {
92 self.in_use.iter().find(|r| predicate(r)).cloned()
93 }
94
95 pub fn get_used_if<P>(&mut self, action: GetAction, predicate: P) -> Option<T> where P: Fn(&T) -> bool, T: Clone {
97 match action {
98 GetAction::Take => self.take_used_if(predicate),
99 GetAction::Clone => self.clone_used_if(predicate),
100 }
101 }
102
103 pub fn get_pending_if<P>(&mut self, predicate: P) -> Option<T> where P: Fn(&T) -> bool, T: Clone {
108 if let Some(ref x) = self.pending {
110 if predicate(x) {
111 Some(x.clone())
112 } else {
113 None
114 }
115 } else {
116 self.in_use.last().into_iter().filter(|x| predicate(x)).next().cloned()
117 }
118 }
119}
120
121#[test]
122fn should_not_find_when_pushed() {
123 let mut q = UsingQueue::new(2);
124 q.set_pending(1);
125 assert!(q.take_used_if(|i| i == &1).is_none());
126}
127
128#[test]
129fn should_not_find_when_pushed_with_clone() {
130 let mut q = UsingQueue::new(2);
131 q.set_pending(1);
132 assert!(q.clone_used_if(|i| i == &1).is_none());
133}
134
135#[test]
136fn should_find_when_pushed_and_used() {
137 let mut q = UsingQueue::new(2);
138 q.set_pending(1);
139 q.use_last_ref();
140 assert!(q.take_used_if(|i| i == &1).unwrap() == 1);
141}
142
143#[test]
144fn should_have_same_semantics_for_get_take_clone() {
145 let mut q = UsingQueue::new(2);
146 q.set_pending(1);
147 assert!(q.get_used_if(GetAction::Clone, |i| i == &1).is_none());
148 assert!(q.get_used_if(GetAction::Take, |i| i == &1).is_none());
149 q.use_last_ref();
150 assert!(q.get_used_if(GetAction::Clone, |i| i == &1).unwrap() == 1);
151 assert!(q.get_used_if(GetAction::Clone, |i| i == &1).unwrap() == 1);
152 assert!(q.get_used_if(GetAction::Take, |i| i == &1).unwrap() == 1);
153 assert!(q.get_used_if(GetAction::Clone, |i| i == &1).is_none());
154 assert!(q.get_used_if(GetAction::Take, |i| i == &1).is_none());
155}
156
157#[test]
158fn should_find_when_pushed_and_used_with_clone() {
159 let mut q = UsingQueue::new(2);
160 q.set_pending(1);
161 q.use_last_ref();
162 assert!(q.clone_used_if(|i| i == &1).unwrap() == 1);
163}
164
165#[test]
166fn should_not_find_again_when_pushed_and_taken() {
167 let mut q = UsingQueue::new(2);
168 q.set_pending(1);
169 q.use_last_ref();
170 assert!(q.take_used_if(|i| i == &1).unwrap() == 1);
171 assert!(q.clone_used_if(|i| i == &1).is_none());
172}
173
174#[test]
175fn should_find_again_when_pushed_and_cloned() {
176 let mut q = UsingQueue::new(2);
177 q.set_pending(1);
178 q.use_last_ref();
179 assert!(q.clone_used_if(|i| i == &1).unwrap() == 1);
180 assert!(q.clone_used_if(|i| i == &1).unwrap() == 1);
181 assert!(q.take_used_if(|i| i == &1).unwrap() == 1);
182}
183
184#[test]
185fn should_find_when_others_used() {
186 let mut q = UsingQueue::new(2);
187 q.set_pending(1);
188 q.use_last_ref();
189 q.set_pending(2);
190 q.use_last_ref();
191 assert!(q.take_used_if(|i| i == &1).is_some());
192}
193
194#[test]
195fn should_not_find_when_too_many_used() {
196 let mut q = UsingQueue::new(1);
197 q.set_pending(1);
198 q.use_last_ref();
199 q.set_pending(2);
200 q.use_last_ref();
201 assert!(q.take_used_if(|i| i == &1).is_none());
202}
203
204#[test]
205fn should_not_find_when_not_used_and_then_pushed() {
206 let mut q = UsingQueue::new(3);
207 q.set_pending(1);
208 q.set_pending(2);
209 q.use_last_ref();
210 assert!(q.take_used_if(|i| i == &1).is_none());
211}
212
213#[test]
214fn should_peek_correctly_after_push() {
215 let mut q = UsingQueue::new(3);
216 q.set_pending(1);
217 assert_eq!(q.peek_last_ref(), Some(&1));
218 q.set_pending(2);
219 assert_eq!(q.peek_last_ref(), Some(&2));
220}
221
222#[test]
223fn should_inspect_correctly() {
224 let mut q = UsingQueue::new(3);
225 q.set_pending(1);
226 assert_eq!(q.use_last_ref(), Some(&1));
227 assert_eq!(q.peek_last_ref(), Some(&1));
228 q.set_pending(2);
229 assert_eq!(q.use_last_ref(), Some(&2));
230 assert_eq!(q.peek_last_ref(), Some(&2));
231}
232
233#[test]
234fn should_not_find_when_not_used_peeked_and_then_pushed() {
235 let mut q = UsingQueue::new(3);
236 q.set_pending(1);
237 q.peek_last_ref();
238 q.set_pending(2);
239 q.use_last_ref();
240 assert!(q.take_used_if(|i| i == &1).is_none());
241}
242
243#[test]
244fn should_pop_used() {
245 let mut q = UsingQueue::new(3);
246 q.set_pending(1);
247 q.use_last_ref();
248 let popped = q.get_pending_if(|i| i == &1);
249 assert_eq!(popped, Some(1));
250}
251
252#[test]
253fn should_not_pop_last_pending() {
254 let mut q = UsingQueue::new(3);
255 q.set_pending(1);
256 assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
257 assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
258}
259
260#[test]
261fn should_not_pop_unused_before_used() {
262 let mut q = UsingQueue::new(3);
263 q.set_pending(1);
264 q.set_pending(2);
265 let popped = q.get_pending_if(|i| i == &1);
266 assert_eq!(popped, None);
267}
268
269#[test]
270fn should_not_remove_used_popped() {
271 let mut q = UsingQueue::new(3);
272 q.set_pending(1);
273 q.use_last_ref();
274 assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
275 assert_eq!(q.get_pending_if(|i| i == &1), Some(1));
276}