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}