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