naia_socket_shared/
time_queue.rs

1use std::{cmp::Ordering, collections::BinaryHeap};
2
3use super::Instant;
4
5/// A queue for items marked by time, will only ever pop items from the queue if
6/// the time passes
7#[derive(Clone)]
8pub struct TimeQueue<T: Eq + PartialEq> {
9    queue: BinaryHeap<ItemContainer<T>>,
10}
11
12#[allow(clippy::new_without_default)]
13impl<T: Eq + PartialEq> TimeQueue<T> {
14    pub fn new() -> Self {
15        Self {
16            queue: BinaryHeap::default(),
17        }
18    }
19}
20
21impl<T: Eq + PartialEq> TimeQueue<T> {
22    /// Adds an item to the queue marked by time
23    pub fn add_item(&mut self, instant: Instant, item: T) {
24        self.queue.push(ItemContainer { instant, item });
25    }
26
27    /// Returns whether or not there is an item whose time has elapsed on the queue
28    pub fn has_item(&self, now: &Instant) -> bool {
29        if self.queue.is_empty() {
30            return false;
31        }
32        if let Some(item) = self.queue.peek() {
33            // item's instant has passed, so it's ready to be returned
34
35            let will_pop = now.is_after(&item.instant);
36
37            return will_pop;
38        }
39        false
40    }
41
42    /// Pops an item from the queue if it's time has elapsed
43    pub fn pop_item(&mut self, now: &Instant) -> Option<T> {
44        if self.has_item(now) {
45            if let Some(container) = self.queue.pop() {
46                return Some(container.item);
47            }
48        }
49        None
50    }
51
52    /// Peeks at the top level item container on the queue
53    pub fn peek_entry(&self) -> Option<&ItemContainer<T>> {
54        self.queue.peek()
55    }
56
57    /// Returns the length of the underlying queue
58    pub fn len(&self) -> usize {
59        self.queue.len()
60    }
61
62    /// Checks if the underlying queue is empty
63    pub fn is_empty(&self) -> bool {
64        self.queue.is_empty()
65    }
66}
67
68#[derive(Clone, Eq, PartialEq)]
69pub struct ItemContainer<T: Eq + PartialEq> {
70    pub instant: Instant,
71    pub item: T,
72}
73
74impl<T: Eq + PartialEq> Ord for ItemContainer<T> {
75    fn cmp(&self, other: &ItemContainer<T>) -> Ordering {
76        other.instant.cmp(&self.instant)
77    }
78}
79
80impl<T: Eq + PartialEq> PartialOrd for ItemContainer<T> {
81    fn partial_cmp(&self, other: &ItemContainer<T>) -> Option<Ordering> {
82        Some(self.cmp(other))
83    }
84}