1#![no_std]
4#![warn(missing_docs)]
5
6use core::{
7 cmp::max,
8 mem::{replace, MaybeUninit},
9};
10
11use cfg_if::cfg_if;
12use safe_modular_arithmetic::StaticModular;
13
14pub trait QueueModel {
16 type Item;
18
19 fn enqueue(&mut self, item: Self::Item) -> bool;
21
22 fn dequeue(&mut self) -> Option<Self::Item>;
25
26 fn is_empty(&self) -> bool;
28}
29
30pub struct StaticRingQueue<T, const N: usize> {
32 length: usize,
33 offset: StaticModular<usize, N>,
34 buffer: [MaybeUninit<T>; N],
35}
36
37impl<T, const N: usize> StaticRingQueue<T, N> {
38 #[inline]
40 pub fn new() -> Self {
41 Self {
42 length: 0,
43 offset: 0.into(),
44 buffer: unsafe { MaybeUninit::uninit().assume_init() },
45 }
46 }
47}
48
49impl<T, const N: usize> Default for StaticRingQueue<T, N> {
50 fn default() -> Self {
51 Self::new()
52 }
53}
54
55impl<T, const N: usize> QueueModel for StaticRingQueue<T, N> {
56 type Item = T;
57
58 fn enqueue(&mut self, item: Self::Item) -> bool {
59 if self.length == N {
60 false
61 } else {
62 self.buffer[self.offset + self.length.into()] = MaybeUninit::new(item);
63 self.length += 1;
64 true
65 }
66 }
67
68 fn dequeue(&mut self) -> Option<Self::Item> {
69 if self.length == 0 {
70 None
71 } else {
72 let item = replace(&mut self.buffer[self.offset], MaybeUninit::uninit());
73 self.offset = self.offset + 1.into();
74 self.length -= 1;
75 Some(unsafe { item.assume_init() })
76 }
77 }
78
79 fn is_empty(&self) -> bool {
80 self.length == 0
81 }
82}
83
84pub struct StaticPriorityQueue<T: Ord, const N: usize> {
86 length: usize,
87 buffer: [MaybeUninit<T>; N],
88}
89
90impl<T: Ord, const N: usize> StaticPriorityQueue<T, N> {
91 #[inline]
93 pub fn new() -> Self {
94 Self {
95 length: 0,
96 buffer: unsafe { MaybeUninit::uninit().assume_init() },
97 }
98 }
99}
100
101impl<T: Ord, const N: usize> Default for StaticPriorityQueue<T, N> {
102 fn default() -> Self {
103 Self::new()
104 }
105}
106
107impl<T: Ord, const N: usize> QueueModel for StaticPriorityQueue<T, N> {
108 type Item = T;
109
110 fn enqueue(&mut self, item: Self::Item) -> bool {
111 if self.length == N {
112 false
113 } else {
114 up_heap(&mut self.buffer[0..=self.length], self.length, item);
115 self.length += 1;
116 true
117 }
118 }
119
120 fn dequeue(&mut self) -> Option<Self::Item> {
121 if self.length == 0 {
122 None
123 } else {
124 self.length -= 1;
125 let last = replace(&mut self.buffer[self.length], MaybeUninit::uninit());
126 let item = down_heap(&mut self.buffer[0..self.length], 0, unsafe {
127 last.assume_init()
128 });
129 Some(unsafe { item.assume_init() })
130 }
131 }
132
133 fn is_empty(&self) -> bool {
134 self.length == 0
135 }
136}
137
138cfg_if! {
139 if #[cfg(feature = "alloc")] {
140 extern crate alloc;
141 use alloc::collections::{BinaryHeap, VecDeque};
142
143 impl<T> QueueModel for VecDeque<T> {
144 type Item = T;
145
146 #[inline]
147 fn enqueue(&mut self, item: Self::Item) -> bool {
148 self.push_back(item);
149 true
150 }
151
152 #[inline]
153 fn dequeue(&mut self) -> Option<Self::Item> {
154 self.pop_front()
155 }
156
157 #[inline]
158 fn is_empty(&self) -> bool {
159 Self::is_empty(&self)
160 }
161 }
162
163 impl<T: Ord> QueueModel for BinaryHeap<T> {
164 type Item = T;
165
166 #[inline]
167 fn enqueue(&mut self, item: Self::Item) -> bool {
168 self.push(item);
169 true
170 }
171
172 #[inline]
173 fn dequeue(&mut self) -> Option<Self::Item> {
174 self.pop()
175 }
176
177 #[inline]
178 fn is_empty(&self) -> bool {
179 Self::is_empty(&self)
180 }
181 }
182 }
183}
184
185fn up_heap<T: Ord>(buffer: &mut [MaybeUninit<T>], index: usize, item: T) -> MaybeUninit<T> {
186 let next = if index == 0 {
187 MaybeUninit::new(item)
188 } else {
189 let parent = (index - 1) / 2;
190 if unsafe { &*(&buffer[parent] as *const _ as *const T) } < &item {
191 up_heap(buffer, parent, item)
192 } else {
193 MaybeUninit::new(item)
194 }
195 };
196 replace(&mut buffer[index], next)
197}
198
199fn down_heap<T: Ord>(buffer: &mut [MaybeUninit<T>], index: usize, item: T) -> MaybeUninit<T> {
200 if index >= buffer.len() {
201 return MaybeUninit::new(item);
202 }
203
204 let child = [index * 2 + 1, index * 2 + 2]
205 .iter()
206 .filter_map(|i| {
207 buffer
208 .get_mut(*i)
209 .map(|v| (unsafe { &*(v as *const _ as *const T) }, *i))
210 })
211 .fold(None, |acc, cur| {
212 if let Some(acc) = acc {
213 Some(max(acc, cur))
214 } else if *cur.0 > item {
215 Some(cur)
216 } else {
217 None
218 }
219 });
220 let next = if let Some((_, i)) = child {
221 down_heap(buffer, i, item)
222 } else {
223 MaybeUninit::new(item)
224 };
225 replace(&mut buffer[index], next)
226}