1#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum QueueStrategy {
6 Fifo,
8 Lifo,
10}
11
12#[derive(Debug, Clone)]
14pub(crate) enum PriorityRule {
15 Default(QueueStrategy),
17 Exact(isize, QueueStrategy),
19 Range(isize, isize, QueueStrategy),
23}
24
25#[derive(Debug, Clone)]
27pub struct PriorityConfig {
28 pub(crate) rules: Vec<PriorityRule>,
29}
30
31impl PriorityConfig {
32 pub fn new() -> Self {
34 Self { rules: Vec::new() }
35 }
36
37 pub fn default_strategy(mut self, strategy: QueueStrategy) -> Self {
39 self.rules.push(PriorityRule::Default(strategy));
40 self
41 }
42
43 pub fn exact(mut self, priority: isize, strategy: QueueStrategy) -> Self {
45 self.rules.push(PriorityRule::Exact(priority, strategy));
46 self
47 }
48
49 pub fn greater_or_equal(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
52 self.rules
53 .push(PriorityRule::Range(threshold, isize::MAX, strategy));
54 self
55 }
56
57 pub fn greater_than(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
60 let min = threshold.saturating_add(1);
61 self.rules
62 .push(PriorityRule::Range(min, isize::MAX, strategy));
63 self
64 }
65
66 pub fn less_or_equal(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
69 self.rules
70 .push(PriorityRule::Range(isize::MIN, threshold, strategy));
71 self
72 }
73
74 pub fn less_than(mut self, threshold: isize, strategy: QueueStrategy) -> Self {
77 let max = threshold.saturating_sub(1);
78 self.rules
79 .push(PriorityRule::Range(isize::MIN, max, strategy));
80 self
81 }
82
83 pub fn range(mut self, min: isize, max: isize, strategy: QueueStrategy) -> Self {
85 self.rules.push(PriorityRule::Range(min, max, strategy));
86 self
87 }
88
89 pub(crate) fn resolve_strategy(&self, priority: isize) -> QueueStrategy {
96 let mut default_strategy = QueueStrategy::Fifo;
97
98 for rule in &self.rules {
100 match rule {
101 PriorityRule::Exact(p, strategy) if *p == priority => return *strategy,
102 PriorityRule::Default(strategy) => default_strategy = *strategy,
103 _ => {}
104 }
105 }
106
107 for rule in &self.rules {
109 match rule {
110 PriorityRule::Range(min, max, strategy) if priority >= *min && priority <= *max => {
111 return *strategy
112 }
113 _ => {}
114 }
115 }
116
117 default_strategy
118 }
119
120 pub fn strategy_for_priority(&self, priority: isize) -> QueueStrategy {
122 self.resolve_strategy(priority)
124 }
125}
126
127impl Default for PriorityConfig {
128 fn default() -> Self {
129 Self::new().default_strategy(QueueStrategy::Fifo)
130 }
131}
132
133#[cfg(test)]
134mod tests {
135 use super::*;
136
137 #[test]
138 fn test_exact_match() {
139 let config = PriorityConfig::new()
140 .default_strategy(QueueStrategy::Fifo)
141 .exact(5, QueueStrategy::Lifo);
142
143 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
144 assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
145 assert_eq!(config.resolve_strategy(6), QueueStrategy::Fifo);
146 }
147
148 #[test]
149 fn test_range_match() {
150 let config = PriorityConfig::new()
151 .default_strategy(QueueStrategy::Fifo)
152 .range(1, 10, QueueStrategy::Lifo);
153
154 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
155 assert_eq!(config.resolve_strategy(1), QueueStrategy::Lifo);
156 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
157 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
158 assert_eq!(config.resolve_strategy(11), QueueStrategy::Fifo);
159 }
160
161 #[test]
162 fn test_greater_or_equal() {
163 let config = PriorityConfig::new()
164 .default_strategy(QueueStrategy::Fifo)
165 .greater_or_equal(5, QueueStrategy::Lifo);
166
167 assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
168 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
169 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
170 }
171
172 #[test]
173 fn test_greater_than() {
174 let config = PriorityConfig::new()
175 .default_strategy(QueueStrategy::Fifo)
176 .greater_than(5, QueueStrategy::Lifo);
177
178 assert_eq!(config.resolve_strategy(5), QueueStrategy::Fifo);
179 assert_eq!(config.resolve_strategy(6), QueueStrategy::Lifo);
180 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
181 }
182
183 #[test]
184 fn test_less_or_equal() {
185 let config = PriorityConfig::new()
186 .default_strategy(QueueStrategy::Lifo)
187 .less_or_equal(0, QueueStrategy::Fifo);
188
189 assert_eq!(config.resolve_strategy(-5), QueueStrategy::Fifo);
190 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
191 assert_eq!(config.resolve_strategy(1), QueueStrategy::Lifo);
192 }
193
194 #[test]
195 fn test_less_than() {
196 let config = PriorityConfig::new()
197 .default_strategy(QueueStrategy::Fifo)
198 .less_than(0, QueueStrategy::Lifo);
199
200 assert_eq!(config.resolve_strategy(-5), QueueStrategy::Lifo);
201 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
202 assert_eq!(config.resolve_strategy(1), QueueStrategy::Fifo);
203 }
204
205 #[test]
206 fn test_priority_order() {
207 let config = PriorityConfig::new()
208 .default_strategy(QueueStrategy::Fifo)
209 .greater_or_equal(5, QueueStrategy::Lifo)
210 .exact(10, QueueStrategy::Fifo); assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
213 assert_eq!(config.resolve_strategy(8), QueueStrategy::Lifo);
214 assert_eq!(config.resolve_strategy(10), QueueStrategy::Fifo); }
216
217 #[test]
218 fn test_multiple_thresholds() {
219 let config = PriorityConfig::new()
220 .default_strategy(QueueStrategy::Fifo)
221 .range(5, isize::MAX, QueueStrategy::Lifo)
222 .range(10, isize::MAX, QueueStrategy::Fifo); assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
225 assert_eq!(config.resolve_strategy(7), QueueStrategy::Lifo);
227 assert_eq!(config.resolve_strategy(15), QueueStrategy::Lifo);
228 }
229}