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 {
120 self.resolve_strategy(priority)
122 }
123}
124
125impl Default for PriorityConfig {
126 fn default() -> Self {
127 Self::new().default_strategy(QueueStrategy::Fifo)
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn test_exact_match() {
137 let config = PriorityConfig::new()
138 .default_strategy(QueueStrategy::Fifo)
139 .exact(5, QueueStrategy::Lifo);
140
141 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
142 assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
143 assert_eq!(config.resolve_strategy(6), QueueStrategy::Fifo);
144 }
145
146 #[test]
147 fn test_range_match() {
148 let config = PriorityConfig::new()
149 .default_strategy(QueueStrategy::Fifo)
150 .range(1, 10, QueueStrategy::Lifo);
151
152 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
153 assert_eq!(config.resolve_strategy(1), QueueStrategy::Lifo);
154 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
155 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
156 assert_eq!(config.resolve_strategy(11), QueueStrategy::Fifo);
157 }
158
159 #[test]
160 fn test_greater_or_equal() {
161 let config = PriorityConfig::new()
162 .default_strategy(QueueStrategy::Fifo)
163 .greater_or_equal(5, QueueStrategy::Lifo);
164
165 assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
166 assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
167 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
168 }
169
170 #[test]
171 fn test_greater_than() {
172 let config = PriorityConfig::new()
173 .default_strategy(QueueStrategy::Fifo)
174 .greater_than(5, QueueStrategy::Lifo);
175
176 assert_eq!(config.resolve_strategy(5), QueueStrategy::Fifo);
177 assert_eq!(config.resolve_strategy(6), QueueStrategy::Lifo);
178 assert_eq!(config.resolve_strategy(10), QueueStrategy::Lifo);
179 }
180
181 #[test]
182 fn test_less_or_equal() {
183 let config = PriorityConfig::new()
184 .default_strategy(QueueStrategy::Lifo)
185 .less_or_equal(0, QueueStrategy::Fifo);
186
187 assert_eq!(config.resolve_strategy(-5), QueueStrategy::Fifo);
188 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
189 assert_eq!(config.resolve_strategy(1), QueueStrategy::Lifo);
190 }
191
192 #[test]
193 fn test_less_than() {
194 let config = PriorityConfig::new()
195 .default_strategy(QueueStrategy::Fifo)
196 .less_than(0, QueueStrategy::Lifo);
197
198 assert_eq!(config.resolve_strategy(-5), QueueStrategy::Lifo);
199 assert_eq!(config.resolve_strategy(0), QueueStrategy::Fifo);
200 assert_eq!(config.resolve_strategy(1), QueueStrategy::Fifo);
201 }
202
203 #[test]
204 fn test_priority_order() {
205 let config = PriorityConfig::new()
206 .default_strategy(QueueStrategy::Fifo)
207 .greater_or_equal(5, QueueStrategy::Lifo)
208 .exact(10, QueueStrategy::Fifo); assert_eq!(config.resolve_strategy(5), QueueStrategy::Lifo);
211 assert_eq!(config.resolve_strategy(8), QueueStrategy::Lifo);
212 assert_eq!(config.resolve_strategy(10), QueueStrategy::Fifo); }
214
215 #[test]
216 fn test_multiple_thresholds() {
217 let config = PriorityConfig::new()
218 .default_strategy(QueueStrategy::Fifo)
219 .range(5, isize::MAX, QueueStrategy::Lifo)
220 .range(10, isize::MAX, QueueStrategy::Fifo); assert_eq!(config.resolve_strategy(4), QueueStrategy::Fifo);
223 assert_eq!(config.resolve_strategy(7), QueueStrategy::Lifo);
225 assert_eq!(config.resolve_strategy(15), QueueStrategy::Lifo);
226 }
227}