1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
3pub enum QueueStrategy {
4 Fifo,
6 Lifo,
8}
9
10#[derive(Debug, Clone)]
12pub(crate) enum PriorityRule {
13 Default(QueueStrategy),
15 Exact(isize, QueueStrategy),
17 Range(isize, isize, QueueStrategy),
21}
22
23#[derive(Debug, Clone)]
25pub struct PriorityConfig {
26 pub(crate) rules: Vec<PriorityRule>,
27}
28
29impl PriorityConfig {
30 pub fn new() -> Self {
32 Self { rules: Vec::new() }
33 }
34
35 pub fn default_strategy(mut self, strategy: QueueStrategy) -> Self {
37 self.rules.push(PriorityRule::Default(strategy));
38 self
39 }
40
41 pub fn exact(mut self, priority: isize, strategy: QueueStrategy) -> Self {
43 self.rules.push(PriorityRule::Exact(priority, strategy));
44 self
45 }
46
47 pub fn greater_or_equal(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
50 self.rules
51 .push(PriorityRule::Range(threshold, isize::MAX, strategy));
52 self
53 }
54
55 pub fn greater_than(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
58 let min = threshold.saturating_add(1);
59 self.rules
60 .push(PriorityRule::Range(min, isize::MAX, strategy));
61 self
62 }
63
64 pub fn less_or_equal(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
67 self.rules
68 .push(PriorityRule::Range(isize::MIN, threshold, strategy));
69 self
70 }
71
72 pub fn less_than(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
75 let max = threshold.saturating_sub(1);
76 self.rules
77 .push(PriorityRule::Range(isize::MIN, max, strategy));
78 self
79 }
80
81 pub fn range(mut self, min: isize, max: isize, strategy: QueueStrategy) -> Self {
83 self.rules.push(PriorityRule::Range(min, max, strategy));
84 self
85 }
86
87 pub(crate) fn resolve_strategy(&self, priority: isize) -> QueueStrategy {
94 let mut default_strategy = QueueStrategy::Fifo;
95
96 for rule in &self.rules {
98 match rule {
99 PriorityRule::Exact(p, strategy) if *p == priority => return *strategy,
100 PriorityRule::Default(strategy) => default_strategy = *strategy,
101 _ => {}
102 }
103 }
104
105 for rule in &self.rules {
107 match rule {
108 PriorityRule::Range(min, max, strategy) if priority >= *min && priority <= *max => {
109 return *strategy
110 }
111 _ => {}
112 }
113 }
114
115 default_strategy
116 }
117
118 pub fn strategy_for_priority(&self, priority: isize) -> QueueStrategy {
144 self.resolve_strategy(priority)
145 }
146}
147
148impl Default for PriorityConfig {
149 fn default() -> Self {
150 Self::new().default_strategy(QueueStrategy::Fifo)
151 }
152}
153
154#[cfg(test)]
155mod tests {
156 use super::*;
157
158 #[test]
159 fn test_exact_match() {
160 let config = PriorityConfig::new()
161 .default_strategy(QueueStrategy::Fifo)
162 .exact(5, QueueStrategy::Lifo);
163
164 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
165 assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
166 assert_eq!(config.resolve_strategy(6), QueueStrategy::Fifo);
167 }
168
169 #[test]
170 fn test_range_match() {
171 let config = PriorityConfig::new()
172 .default_strategy(QueueStrategy::Fifo)
173 .range(1, 10, QueueStrategy::Lifo);
174
175 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
176 assert_eq!(config.resolve_strategy(1), QueueStrategy::Lifo);
177 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
178 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
179 assert_eq!(config.resolve_strategy(11), QueueStrategy::Fifo);
180 }
181
182 #[test]
183 fn test_greater_or_equal() {
184 let config = PriorityConfig::new()
185 .default_strategy(QueueStrategy::Fifo)
186 .greater_or_equal(5, QueueStrategy::Lifo);
187
188 assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
189 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
190 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
191 }
192
193 #[test]
194 fn test_greater_than() {
195 let config = PriorityConfig::new()
196 .default_strategy(QueueStrategy::Fifo)
197 .greater_than(5, QueueStrategy::Lifo);
198
199 assert_eq!(config.resolve_strategy(5), QueueStrategy::Fifo);
200 assert_eq!(config.resolve_strategy(6), QueueStrategy::Lifo);
201 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
202 }
203
204 #[test]
205 fn test_less_or_equal() {
206 let config = PriorityConfig::new()
207 .default_strategy(QueueStrategy::Lifo)
208 .less_or_equal(0, QueueStrategy::Fifo);
209
210 assert_eq!(config.resolve_strategy(-5), QueueStrategy::Fifo);
211 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
212 assert_eq!(config.resolve_strategy(1), QueueStrategy::Lifo);
213 }
214
215 #[test]
216 fn test_less_than() {
217 let config = PriorityConfig::new()
218 .default_strategy(QueueStrategy::Fifo)
219 .less_than(0, QueueStrategy::Lifo);
220
221 assert_eq!(config.resolve_strategy(-5), QueueStrategy::Lifo);
222 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
223 assert_eq!(config.resolve_strategy(1), QueueStrategy::Fifo);
224 }
225
226 #[test]
227 fn test_priority_order() {
228 let config = PriorityConfig::new()
229 .default_strategy(QueueStrategy::Fifo)
230 .greater_or_equal(5, QueueStrategy::Lifo)
231 .exact(10, QueueStrategy::Fifo); assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
234 assert_eq!(config.resolve_strategy(8), QueueStrategy::Lifo);
235 assert_eq!(config.resolve_strategy(10), QueueStrategy::Fifo); }
237
238 #[test]
239 fn test_multiple_thresholds() {
240 let config = PriorityConfig::new()
241 .default_strategy(QueueStrategy::Fifo)
242 .range(5, isize::MAX, QueueStrategy::Lifo)
243 .range(10, isize::MAX, QueueStrategy::Fifo); assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
246 assert_eq!(config.resolve_strategy(7), QueueStrategy::Lifo);
248 assert_eq!(config.resolve_strategy(15), QueueStrategy::Lifo);
249 }
250}