squeue/queue.rs
1// Copyright (C) 2024 Christian Mauduit <ufoot@ufoot.org>
2
3use crate::drain::Drain;
4use std::collections::vec_deque::IntoIter;
5use std::collections::VecDeque;
6use std::fmt;
7
8/// FIFO queue with a fixed capacity.
9///
10/// This is in a LRU package because it has a semantic behavior
11/// similar to an LRU, in the sense that when capacity is reached,
12/// the oldest element is dropped.
13///
14/// In practice it in just some syntaxic sugar over a `VecDeque`,
15/// and data is dropped when you exceed capacity.
16///
17/// # Examples
18///
19/// ```
20/// use squeue::Queue;
21///
22/// let mut queue: Queue<usize> = Queue::new(3);
23/// assert_eq!(None, queue.push(1));
24/// assert_eq!(None, queue.push(2));
25/// assert_eq!(None, queue.push(3));
26/// assert_eq!(Some(1), queue.push(4));
27/// assert_eq!(3, queue.len());
28/// ```
29#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
30#[derive(Debug, Clone)]
31pub struct Queue<T> {
32 capacity: usize,
33 data: VecDeque<T>,
34}
35
36/// Pretty-print queue content.
37///
38/// Prints the next element to be popped, and the len/capacity.
39///
40/// # Examples
41///
42/// ```
43/// use squeue::Queue;
44///
45/// let mut queue = Queue::new(100);
46/// queue.push(123);
47/// queue.push(4);
48/// queue.push(5);
49/// assert_eq!("{ next: 123, len: 3, capacity: 100 }", format!("{}", queue));
50/// queue.clear();
51/// assert_eq!("{ len: 0, capacity: 100 }", format!("{}", queue));
52/// ```
53impl<T> fmt::Display for Queue<T>
54where
55 T: fmt::Display,
56{
57 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
58 match self.peek() {
59 Some(item) => write!(
60 f,
61 "{{ next: {}, len: {}, capacity: {} }}",
62 item,
63 self.len(),
64 self.capacity()
65 ),
66 None => write!(
67 f,
68 "{{ len: {}, capacity: {} }}",
69 self.len(),
70 self.capacity()
71 ),
72 }
73 }
74}
75
76impl<T> Queue<T> {
77 /// Create a new queue.
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use squeue::Queue;
83 ///
84 /// let queue: Queue<String> = Queue::new(10);
85 /// assert_eq!(10, queue.capacity());
86 /// ```
87 pub fn new(capacity: usize) -> Self {
88 Queue {
89 capacity,
90 data: VecDeque::with_capacity(capacity + 1),
91 }
92 }
93
94 /// Return queue length.
95 ///
96 /// # Examples
97 ///
98 /// ```
99 /// use squeue::Queue;
100 ///
101 /// let mut queue: Queue<&str> = Queue::new(10);
102 /// assert_eq!(0, queue.len());
103 /// queue.push("x");
104 /// queue.push("y");
105 /// assert_eq!(2, queue.len());
106 /// ```
107 #[inline]
108 pub fn len(&self) -> usize {
109 self.data.len()
110 }
111
112 /// Return queue capacity.
113 ///
114 /// # Examples
115 ///
116 /// ```
117 /// use squeue::Queue;
118 ///
119 /// let mut queue: Queue<f64> = Queue::new(100);
120 /// assert_eq!(100, queue.capacity());
121 /// ```
122 #[inline]
123 pub fn capacity(&self) -> usize {
124 self.capacity
125 }
126
127 /// Returns true if queue is empty.
128 ///
129 /// # Examples
130 ///
131 /// ```
132 /// use squeue::Queue;
133 ///
134 /// let mut queue: Queue<String> = Queue::new(100);
135 /// assert!(queue.is_empty());
136 /// queue.push(String::from("abc"));
137 /// assert!(!queue.is_empty());
138 /// ```
139 #[inline]
140 pub fn is_empty(&self) -> bool {
141 self.data.is_empty()
142 }
143
144 /// Returns true if queue is full.
145 ///
146 /// # Examples
147 ///
148 /// ```
149 /// use squeue::Queue;
150 ///
151 /// let mut queue: Queue<usize> = Queue::new(10);
152 /// assert!(!queue.is_full());
153 /// for i in 0..10 {
154 /// queue.push(i);
155 /// }
156 /// assert!(queue.is_full());
157 /// ```
158 #[inline]
159 pub fn is_full(&self) -> bool {
160 self.len() >= self.capacity()
161 }
162
163 /// Clear all data.
164 ///
165 /// # Examples
166 ///
167 /// ```
168 /// use squeue::Queue;
169 ///
170 /// let mut queue: Queue<String> = Queue::new(100);
171 /// queue.push(String::from("abc"));
172 /// queue.clear();
173 /// assert!(queue.is_empty());
174 /// ```
175 #[inline]
176 pub fn clear(&mut self) {
177 self.data.clear()
178 }
179
180 /// Resize queue.
181 ///
182 /// Returns the number of dropped items, if any.
183 ///
184 /// # Examples
185 ///
186 /// ```
187 /// use squeue::Queue;
188 ///
189 /// let mut queue: Queue<usize> = Queue::new(10);
190 /// assert_eq!(10, queue.capacity());
191 /// assert_eq!(0, queue.resize(100));
192 /// assert_eq!(100, queue.capacity());
193 /// for i in 0..1000 {
194 /// queue.push(i);
195 /// }
196 /// assert_eq!(100, queue.len());
197 /// assert_eq!(90, queue.resize(10));
198 /// assert_eq!(10, queue.capacity());
199 /// assert_eq!(10, queue.len());
200 /// assert_eq!(Some(990), queue.pop());
201 /// ```
202 pub fn resize(&mut self, capacity: usize) -> usize {
203 self.capacity = capacity;
204 let old_size = self.data.len();
205 if old_size > capacity {
206 self.data.truncate(capacity);
207 old_size - capacity
208 } else {
209 if capacity > old_size {
210 self.data.try_reserve(capacity + 1 - old_size).ok();
211 }
212 0
213 }
214 }
215
216 /// Push data into the queue.
217 ///
218 /// If the queue is full and data needs to be dropped,
219 /// that data is returned.
220 ///
221 /// # Examples
222 ///
223 /// ```
224 /// use squeue::Queue;
225 ///
226 /// let mut queue: Queue<usize> = Queue::new(2);
227 /// assert_eq!(None, queue.push(1));
228 /// assert_eq!(None, queue.push(10));
229 /// assert_eq!(Some(1), queue.push(100));
230 /// assert_eq!(Some(10), queue.push(1000));
231 /// assert_eq!(2, queue.len());
232 /// ```
233 pub fn push(&mut self, item: T) -> Option<T> {
234 if self.capacity == 0 {
235 return None;
236 }
237 self.data.push_front(item);
238 if self.data.len() > self.capacity {
239 self.pop()
240 } else {
241 None
242 }
243 }
244
245 /// Pop data from the queue.
246 ///
247 /// The oldest item is returned, this works in FIFO mode.
248 ///
249 /// # Examples
250 ///
251 /// ```
252 /// use squeue::Queue;
253 ///
254 /// let mut queue: Queue<usize> = Queue::new(5);
255 /// assert_eq!(None, queue.pop());
256 /// assert_eq!(None, queue.push(1));
257 /// assert_eq!(Some(1), queue.pop());
258 /// assert_eq!(None, queue.push(2));
259 /// assert_eq!(None, queue.push(3));
260 /// assert_eq!(Some(2), queue.pop());
261 /// assert_eq!(1, queue.len());
262 /// ```
263 pub fn pop(&mut self) -> Option<T> {
264 self.data.pop_back()
265 }
266
267 /// Peek data, get it without removing it.
268 ///
269 /// This gives an insight on what pop() would return.
270 ///
271 /// # Examples
272 ///
273 /// ```
274 /// use squeue::Queue;
275 ///
276 /// let mut queue: Queue<usize> = Queue::new(5);
277 /// assert_eq!(None, queue.peek());
278 /// assert_eq!(None, queue.push(1));
279 /// assert_eq!(None, queue.push(2));
280 /// assert_eq!(Some(&1), queue.peek());
281 /// ```
282 pub fn peek(&self) -> Option<&T> {
283 // May sound a little convoluted, why not use
284 // 0 as the "where we pop things" just do
285 // queue.get(0). The reason is that if we
286 // do this, truncate() does not work as expected
287 // and drops recent entries.
288 let len = self.data.len();
289 if len > 0 {
290 self.data.get(len - 1)
291 } else {
292 None
293 }
294 }
295
296 /// Creates an iterator which drains the queue.
297 ///
298 /// Use this when you want to get all the items, at a given point,
299 /// and free space in the queue.
300 ///
301 /// ```
302 /// use squeue::Queue;
303 ///
304 /// let mut queue = Queue::new(10);
305 /// queue.push(1);
306 /// queue.push(10);
307 /// let drain = queue.drain();
308 /// assert_eq!(0, queue.len());
309 /// assert_eq!(2, drain.count());
310 /// ```
311 pub fn drain(&mut self) -> Drain<T> {
312 Drain::new(self)
313 }
314}
315
316impl<T> std::iter::IntoIterator for Queue<T> {
317 type Item = T;
318 type IntoIter = IntoIter<T>;
319
320 /// Creates an iterator over the queue.
321 ///
322 /// Takes ownership.
323 ///
324 /// # Examples
325 ///
326 /// ```
327 /// use squeue::Queue;
328 ///
329 /// let mut queue = Queue::new(10);
330 /// queue.push(4);
331 /// queue.push(5);
332 /// queue.push(6);
333 ///
334 /// let sum=queue.into_iter().sum();
335 /// assert_eq!(15, sum);
336 /// ```
337 fn into_iter(self) -> IntoIter<T> {
338 self.data.into_iter()
339 }
340}
341
342impl<T> FromIterator<T> for Queue<T> {
343 /// Creates a new queue from an iterator.
344 ///
345 /// With this, you can use collect() to build a queue.
346 ///
347 /// # Examples
348 ///
349 /// ```
350 /// use squeue::Queue;
351 ///
352 /// let src: Vec<usize> = vec![4, 5, 6];
353 ///
354 /// let mut queue = src.into_iter().collect::<Queue<usize>>();
355 /// assert_eq!(Some(4), queue.pop());
356 /// assert_eq!(Some(5), queue.pop());
357 /// assert_eq!(Some(6), queue.pop());
358 /// assert_eq!(None, queue.pop());
359 /// assert_eq!(3, queue.capacity());
360 /// ```
361 fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
362 let mut queue = Queue::new(0);
363
364 for i in iter {
365 queue.resize(queue.len() + 1);
366 queue.push(i);
367 }
368
369 queue
370 }
371}
372
373impl<T> PartialEq<Queue<T>> for Queue<T>
374where
375 T: PartialEq,
376{
377 /// Compares two queues. Capacity, content and order must match.
378 ///
379 /// # Examples
380 ///
381 /// ```
382 /// use squeue::Queue;
383 ///
384 /// let mut queue1 = Queue::new(10);
385 /// queue1.push("Alice");
386 /// queue1.push("Bob");
387 /// let mut queue2 = Queue::new(10);
388 /// queue2.push("Oscar");
389 /// queue2.push("Alice");
390 /// queue2.push("Bob");
391 /// assert_ne!(&queue1, &queue2);
392 /// queue2.pop();
393 /// assert_eq!(&queue1, &queue2);
394 /// ```
395 fn eq(&self, other: &Self) -> bool {
396 if self.capacity != other.capacity {
397 return false;
398 }
399 if self.len() != other.len() {
400 return false;
401 }
402 let mut iter_other = other.data.iter();
403 for self_v in self.data.iter() {
404 match iter_other.next() {
405 Some(other_v) => {
406 if self_v != other_v {
407 return false;
408 }
409 }
410 None => return false,
411 }
412 }
413 true
414 }
415}
416
417impl<T> Eq for Queue<T> where T: Eq {}
418
419#[cfg(test)]
420mod tests {
421 use super::*;
422
423 #[test]
424 fn test_queue_0() {
425 let mut queue: Queue<usize> = Queue::new(0);
426 assert_eq!(None, queue.push(42));
427 assert_eq!(None, queue.pop());
428 assert_eq!(0, queue.capacity());
429 assert_eq!(true, queue.is_full());
430 assert_eq!(true, queue.is_empty());
431 }
432
433 #[cfg(feature = "serde")]
434 #[test]
435 fn test_json() {
436 use serde_json::json;
437
438 let mut queue1 = Queue::<usize>::new(10);
439
440 queue1.push(1);
441 queue1.push(2);
442
443 let export = json!(&queue1).to_string();
444
445 assert_eq!("{\"capacity\":10,\"data\":[2,1]}", export);
446
447 let queue2: Queue<usize> = serde_json::from_str(&export).unwrap();
448
449 assert_eq!(&queue1, &queue2);
450 queue1.clear();
451 assert_eq!(0, queue1.len());
452 assert_eq!(2, queue2.len());
453 }
454}