oxihuman_core/
notification_queue.rs1#![allow(dead_code)]
4
5use std::cmp::Ordering;
8use std::collections::BinaryHeap;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub enum NotifPriority {
13 Low = 0,
14 Normal = 1,
15 High = 2,
16 Critical = 3,
17}
18
19#[derive(Debug, Clone)]
21pub struct Notification {
22 pub id: u64,
23 pub priority: NotifPriority,
24 pub title: String,
25 pub body: String,
26}
27
28#[derive(Debug)]
29struct PrioritizedNotif {
30 notif: Notification,
31}
32
33impl PartialEq for PrioritizedNotif {
34 fn eq(&self, other: &Self) -> bool {
35 self.notif.priority as u8 == other.notif.priority as u8 && self.notif.id == other.notif.id
36 }
37}
38impl Eq for PrioritizedNotif {}
39
40impl PartialOrd for PrioritizedNotif {
41 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
42 Some(self.cmp(other))
43 }
44}
45
46impl Ord for PrioritizedNotif {
47 fn cmp(&self, other: &Self) -> Ordering {
48 (self.notif.priority as u8)
49 .cmp(&(other.notif.priority as u8))
50 .then(other.notif.id.cmp(&self.notif.id))
51 }
52}
53
54#[derive(Debug, Default)]
56pub struct NotificationQueue {
57 heap: BinaryHeap<PrioritizedNotif>,
58 next_id: u64,
59}
60
61impl NotificationQueue {
62 pub fn new() -> Self {
63 Self::default()
64 }
65
66 pub fn push(&mut self, priority: NotifPriority, title: &str, body: &str) -> u64 {
67 let id = self.next_id;
68 self.next_id += 1;
69 self.heap.push(PrioritizedNotif {
70 notif: Notification {
71 id,
72 priority,
73 title: title.to_string(),
74 body: body.to_string(),
75 },
76 });
77 id
78 }
79
80 pub fn pop(&mut self) -> Option<Notification> {
81 self.heap.pop().map(|p| p.notif)
82 }
83
84 pub fn peek_priority(&self) -> Option<NotifPriority> {
85 self.heap.peek().map(|p| p.notif.priority)
86 }
87
88 pub fn len(&self) -> usize {
89 self.heap.len()
90 }
91
92 pub fn is_empty(&self) -> bool {
93 self.heap.is_empty()
94 }
95}
96
97pub fn new_notification_queue() -> NotificationQueue {
98 NotificationQueue::new()
99}
100
101pub fn nq_push(q: &mut NotificationQueue, priority: NotifPriority, title: &str, body: &str) -> u64 {
102 q.push(priority, title, body)
103}
104
105pub fn nq_pop(q: &mut NotificationQueue) -> Option<Notification> {
106 q.pop()
107}
108
109pub fn nq_len(q: &NotificationQueue) -> usize {
110 q.len()
111}
112
113pub fn nq_peek_priority(q: &NotificationQueue) -> Option<NotifPriority> {
114 q.peek_priority()
115}
116
117pub fn nq_is_empty(q: &NotificationQueue) -> bool {
118 q.is_empty()
119}
120
121#[cfg(test)]
122mod tests {
123 use super::*;
124
125 #[test]
126 fn test_push_and_len() {
127 let mut q = new_notification_queue();
128 nq_push(&mut q, NotifPriority::Normal, "Hello", "World");
129 assert_eq!(nq_len(&q), 1);
130 }
131
132 #[test]
133 fn test_pop_returns_item() {
134 let mut q = new_notification_queue();
135 nq_push(&mut q, NotifPriority::Normal, "T", "B");
136 let n = nq_pop(&mut q).expect("should succeed");
137 assert_eq!(n.title, "T");
138 }
139
140 #[test]
141 fn test_priority_ordering() {
142 let mut q = new_notification_queue();
144 nq_push(&mut q, NotifPriority::Low, "low", "");
145 nq_push(&mut q, NotifPriority::Critical, "crit", "");
146 nq_push(&mut q, NotifPriority::Normal, "norm", "");
147 let first = nq_pop(&mut q).expect("should succeed");
148 assert_eq!(first.priority, NotifPriority::Critical);
149 }
150
151 #[test]
152 fn test_peek_priority() {
153 let mut q = new_notification_queue();
154 nq_push(&mut q, NotifPriority::High, "h", "");
155 assert_eq!(nq_peek_priority(&q), Some(NotifPriority::High));
156 }
157
158 #[test]
159 fn test_is_empty_initially() {
160 let q = new_notification_queue();
161 assert!(nq_is_empty(&q));
162 }
163
164 #[test]
165 fn test_pop_empty_returns_none() {
166 let mut q = new_notification_queue();
167 assert!(nq_pop(&mut q).is_none());
168 }
169
170 #[test]
171 fn test_id_increments() {
172 let mut q = new_notification_queue();
173 let id0 = nq_push(&mut q, NotifPriority::Low, "a", "");
174 let id1 = nq_push(&mut q, NotifPriority::Low, "b", "");
175 assert_ne!(id0, id1);
176 }
177
178 #[test]
179 fn test_multiple_pops_drain_queue() {
180 let mut q = new_notification_queue();
181 nq_push(&mut q, NotifPriority::Low, "a", "");
182 nq_push(&mut q, NotifPriority::Low, "b", "");
183 nq_pop(&mut q);
184 nq_pop(&mut q);
185 assert!(nq_is_empty(&q));
186 }
187
188 #[test]
189 fn test_high_before_normal() {
190 let mut q = new_notification_queue();
191 nq_push(&mut q, NotifPriority::Normal, "n", "");
192 nq_push(&mut q, NotifPriority::High, "h", "");
193 let first = nq_pop(&mut q).expect("should succeed");
194 assert_eq!(first.priority, NotifPriority::High);
195 }
196}