1use super::FlowSpecError;
2
3#[derive(Debug, Clone, PartialEq, Eq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6pub struct NumericOperator {
7 pub end_of_list: bool,
9 pub and_with_next: bool,
11 pub value_length: u8,
13 pub less_than: bool,
15 pub greater_than: bool,
17 pub equal: bool,
19 pub value: u64,
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
26pub struct BitmaskOperator {
27 pub end_of_list: bool,
29 pub and_with_next: bool,
31 pub value_length: u8,
33 pub not: bool,
35 pub match_flag: bool,
37 pub bitmask: u64,
39}
40
41impl NumericOperator {
42 pub fn from_byte_and_value(operator_byte: u8, value: u64) -> Result<Self, FlowSpecError> {
44 let value_length = match (operator_byte >> 4) & 0x03 {
45 0 => 1,
46 1 => 2,
47 2 => 4,
48 3 => 8,
49 _ => return Err(FlowSpecError::InvalidOperator(operator_byte)),
50 };
51
52 if (operator_byte & 0x08) != 0 {
54 return Err(FlowSpecError::InvalidOperator(operator_byte));
55 }
56
57 Ok(NumericOperator {
58 end_of_list: (operator_byte & 0x80) != 0,
59 and_with_next: (operator_byte & 0x40) != 0,
60 value_length,
61 less_than: (operator_byte & 0x04) != 0,
62 greater_than: (operator_byte & 0x02) != 0,
63 equal: (operator_byte & 0x01) != 0,
64 value,
65 })
66 }
67
68 pub fn to_byte(&self) -> u8 {
70 let mut byte = 0u8;
71
72 if self.end_of_list {
73 byte |= 0x80;
74 }
75 if self.and_with_next {
76 byte |= 0x40;
77 }
78
79 let len_bits = match self.value_length {
81 1 => 0x00,
82 2 => 0x10,
83 4 => 0x20,
84 8 => 0x30,
85 _ => 0x00, };
87 byte |= len_bits;
88
89 if self.less_than {
92 byte |= 0x04;
93 }
94 if self.greater_than {
95 byte |= 0x02;
96 }
97 if self.equal {
98 byte |= 0x01;
99 }
100
101 byte
102 }
103
104 pub fn equal_to(value: u64) -> Self {
106 let value_length = if value <= 0xFF {
107 1
108 } else if value <= 0xFFFF {
109 2
110 } else if value <= 0xFFFFFFFF {
111 4
112 } else {
113 8
114 };
115
116 NumericOperator {
117 end_of_list: true,
118 and_with_next: false,
119 value_length,
120 less_than: false,
121 greater_than: false,
122 equal: true,
123 value,
124 }
125 }
126
127 pub fn greater_than_or_equal(value: u64) -> Self {
129 let value_length = if value <= 0xFF {
130 1
131 } else if value <= 0xFFFF {
132 2
133 } else if value <= 0xFFFFFFFF {
134 4
135 } else {
136 8
137 };
138
139 NumericOperator {
140 end_of_list: true,
141 and_with_next: false,
142 value_length,
143 less_than: false,
144 greater_than: true,
145 equal: true,
146 value,
147 }
148 }
149}
150
151impl BitmaskOperator {
152 pub fn from_byte_and_value(operator_byte: u8, bitmask: u64) -> Result<Self, FlowSpecError> {
154 let value_length = match (operator_byte >> 4) & 0x03 {
155 0 => 1,
156 1 => 2,
157 2 => 4,
158 3 => 8,
159 _ => return Err(FlowSpecError::InvalidOperator(operator_byte)),
160 };
161
162 if (operator_byte & 0x0C) != 0 {
164 return Err(FlowSpecError::InvalidOperator(operator_byte));
165 }
166
167 Ok(BitmaskOperator {
168 end_of_list: (operator_byte & 0x80) != 0,
169 and_with_next: (operator_byte & 0x40) != 0,
170 value_length,
171 not: (operator_byte & 0x02) != 0,
172 match_flag: (operator_byte & 0x01) != 0,
173 bitmask,
174 })
175 }
176
177 pub fn to_byte(&self) -> u8 {
179 let mut byte = 0u8;
180
181 if self.end_of_list {
182 byte |= 0x80;
183 }
184 if self.and_with_next {
185 byte |= 0x40;
186 }
187
188 let len_bits = match self.value_length {
190 1 => 0x00,
191 2 => 0x10,
192 4 => 0x20,
193 8 => 0x30,
194 _ => 0x00, };
196 byte |= len_bits;
197
198 if self.not {
201 byte |= 0x02;
202 }
203 if self.match_flag {
204 byte |= 0x01;
205 }
206
207 byte
208 }
209
210 pub fn exact_match(bitmask: u64) -> Self {
212 let value_length = if bitmask <= 0xFF {
213 1
214 } else if bitmask <= 0xFFFF {
215 2
216 } else if bitmask <= 0xFFFFFFFF {
217 4
218 } else {
219 8
220 };
221
222 BitmaskOperator {
223 end_of_list: true,
224 and_with_next: false,
225 value_length,
226 not: false,
227 match_flag: false,
228 bitmask,
229 }
230 }
231
232 pub fn partial_match(bitmask: u64) -> Self {
234 let value_length = if bitmask <= 0xFF {
235 1
236 } else if bitmask <= 0xFFFF {
237 2
238 } else if bitmask <= 0xFFFFFFFF {
239 4
240 } else {
241 8
242 };
243
244 BitmaskOperator {
245 end_of_list: true,
246 and_with_next: false,
247 value_length,
248 not: false,
249 match_flag: true,
250 bitmask,
251 }
252 }
253}
254
255#[cfg(test)]
256mod tests {
257 use super::*;
258
259 #[test]
260 fn test_numeric_operator_creation() {
261 let op = NumericOperator::equal_to(25);
262 assert!(op.equal);
263 assert!(!op.less_than);
264 assert!(!op.greater_than);
265 assert_eq!(op.value, 25);
266 assert_eq!(op.value_length, 1);
267 }
268
269 #[test]
270 fn test_numeric_operator_byte_conversion() {
271 let op = NumericOperator {
272 end_of_list: true,
273 and_with_next: false,
274 value_length: 1,
275 less_than: false,
276 greater_than: false,
277 equal: true,
278 value: 25,
279 };
280
281 let byte = op.to_byte();
282 assert_eq!(byte, 0x81); let parsed_op = NumericOperator::from_byte_and_value(byte, 25).unwrap();
285 assert_eq!(parsed_op.end_of_list, op.end_of_list);
286 assert_eq!(parsed_op.equal, op.equal);
287 assert_eq!(parsed_op.value, op.value);
288 }
289
290 #[test]
291 fn test_bitmask_operator_creation() {
292 let op = BitmaskOperator::exact_match(0x06); assert!(!op.match_flag);
294 assert!(!op.not);
295 assert_eq!(op.bitmask, 0x06);
296 assert_eq!(op.value_length, 1);
297 }
298
299 #[test]
300 fn test_invalid_operator_byte() {
301 let result = NumericOperator::from_byte_and_value(0x08, 25);
303 assert!(matches!(result, Err(FlowSpecError::InvalidOperator(0x08))));
304
305 let result = BitmaskOperator::from_byte_and_value(0x0C, 25);
307 assert!(matches!(result, Err(FlowSpecError::InvalidOperator(0x0C))));
308 }
309
310 #[test]
311 fn test_numeric_operator_various_lengths() {
312 let op1 = NumericOperator::equal_to(255);
314 assert_eq!(op1.value_length, 1);
315 assert_eq!(op1.value, 255);
316
317 let op2 = NumericOperator::equal_to(256);
319 assert_eq!(op2.value_length, 2);
320 assert_eq!(op2.value, 256);
321
322 let op4 = NumericOperator::equal_to(0x10000);
324 assert_eq!(op4.value_length, 4);
325 assert_eq!(op4.value, 0x10000);
326
327 let op8 = NumericOperator::equal_to(0x100000000);
329 assert_eq!(op8.value_length, 8);
330 assert_eq!(op8.value, 0x100000000);
331 }
332
333 #[test]
334 fn test_bitmask_operator_various_lengths() {
335 let op1 = BitmaskOperator::exact_match(255);
337 assert_eq!(op1.value_length, 1);
338 assert_eq!(op1.bitmask, 255);
339
340 let op2 = BitmaskOperator::exact_match(256);
342 assert_eq!(op2.value_length, 2);
343 assert_eq!(op2.bitmask, 256);
344
345 let op4 = BitmaskOperator::exact_match(0x10000);
347 assert_eq!(op4.value_length, 4);
348 assert_eq!(op4.bitmask, 0x10000);
349
350 let op8 = BitmaskOperator::exact_match(0x100000000);
352 assert_eq!(op8.value_length, 8);
353 assert_eq!(op8.bitmask, 0x100000000);
354 }
355
356 #[test]
357 fn test_numeric_operator_greater_than_or_equal() {
358 let op = NumericOperator::greater_than_or_equal(1000);
359 assert!(op.greater_than);
360 assert!(op.equal);
361 assert!(!op.less_than);
362 assert!(op.end_of_list);
363 assert!(!op.and_with_next);
364 assert_eq!(op.value, 1000);
365 assert_eq!(op.value_length, 2);
366 }
367
368 #[test]
369 fn test_bitmask_operator_partial_match() {
370 let op = BitmaskOperator::partial_match(0x06);
371 assert!(op.match_flag);
372 assert!(!op.not);
373 assert!(op.end_of_list);
374 assert!(!op.and_with_next);
375 assert_eq!(op.bitmask, 0x06);
376 assert_eq!(op.value_length, 1);
377 }
378
379 #[test]
380 fn test_numeric_operator_complex_byte_encoding() {
381 let op = NumericOperator {
383 end_of_list: false,
384 and_with_next: true,
385 value_length: 2,
386 less_than: true,
387 greater_than: false,
388 equal: true,
389 value: 443,
390 };
391
392 let byte = op.to_byte();
393 assert_eq!(byte, 0x55);
395
396 let parsed_op = NumericOperator::from_byte_and_value(byte, 443).unwrap();
397 assert_eq!(parsed_op.end_of_list, op.end_of_list);
398 assert_eq!(parsed_op.and_with_next, op.and_with_next);
399 assert_eq!(parsed_op.value_length, op.value_length);
400 assert_eq!(parsed_op.less_than, op.less_than);
401 assert_eq!(parsed_op.greater_than, op.greater_than);
402 assert_eq!(parsed_op.equal, op.equal);
403 assert_eq!(parsed_op.value, op.value);
404 }
405
406 #[test]
407 fn test_bitmask_operator_complex_byte_encoding() {
408 let op = BitmaskOperator {
410 end_of_list: false,
411 and_with_next: true,
412 value_length: 4,
413 not: true,
414 match_flag: true,
415 bitmask: 0xFF000000,
416 };
417
418 let byte = op.to_byte();
419 assert_eq!(byte, 0x63);
421
422 let parsed_op = BitmaskOperator::from_byte_and_value(byte, 0xFF000000).unwrap();
423 assert_eq!(parsed_op.end_of_list, op.end_of_list);
424 assert_eq!(parsed_op.and_with_next, op.and_with_next);
425 assert_eq!(parsed_op.value_length, op.value_length);
426 assert_eq!(parsed_op.not, op.not);
427 assert_eq!(parsed_op.match_flag, op.match_flag);
428 assert_eq!(parsed_op.bitmask, op.bitmask);
429 }
430
431 #[test]
432 fn test_operator_invalid_length_defaults() {
433 let mut op = NumericOperator::equal_to(25);
435 op.value_length = 7; let byte = op.to_byte();
437 assert_eq!(byte & 0x30, 0x00);
439
440 let mut bm_op = BitmaskOperator::exact_match(25);
441 bm_op.value_length = 9; let byte = bm_op.to_byte();
443 assert_eq!(byte & 0x30, 0x00);
445 }
446
447 #[test]
448 fn test_numeric_operator_all_comparison_flags() {
449 let op = NumericOperator {
451 end_of_list: true,
452 and_with_next: false,
453 value_length: 1,
454 less_than: true,
455 greater_than: true,
456 equal: true,
457 value: 100,
458 };
459
460 let byte = op.to_byte();
461 assert_eq!(byte, 0x87); let parsed_op = NumericOperator::from_byte_and_value(byte, 100).unwrap();
464 assert!(parsed_op.less_than);
465 assert!(parsed_op.greater_than);
466 assert!(parsed_op.equal);
467 }
468
469 #[test]
470 fn test_bitmask_operator_edge_cases() {
471 let op_not_exact = BitmaskOperator {
473 end_of_list: true,
474 and_with_next: false,
475 value_length: 1,
476 not: true,
477 match_flag: false,
478 bitmask: 0x42,
479 };
480
481 let byte = op_not_exact.to_byte();
482 assert_eq!(byte, 0x82); let parsed_op = BitmaskOperator::from_byte_and_value(byte, 0x42).unwrap();
485 assert!(parsed_op.not);
486 assert!(!parsed_op.match_flag);
487 }
488
489 #[test]
490 fn test_operator_length_encoding_all_values() {
491 for (expected_len, len_bits) in [(1, 0x00), (2, 0x10), (4, 0x20), (8, 0x30)] {
493 let op = NumericOperator {
494 end_of_list: true,
495 and_with_next: false,
496 value_length: expected_len,
497 less_than: false,
498 greater_than: false,
499 equal: true,
500 value: 42,
501 };
502
503 let byte = op.to_byte();
504 assert_eq!(byte & 0x30, len_bits);
505
506 let parsed_op = NumericOperator::from_byte_and_value(byte, 42).unwrap();
507 assert_eq!(parsed_op.value_length, expected_len);
508 }
509
510 for (expected_len, len_bits) in [(1, 0x00), (2, 0x10), (4, 0x20), (8, 0x30)] {
512 let op = BitmaskOperator {
513 end_of_list: true,
514 and_with_next: false,
515 value_length: expected_len,
516 not: false,
517 match_flag: true,
518 bitmask: 42,
519 };
520
521 let byte = op.to_byte();
522 assert_eq!(byte & 0x30, len_bits);
523
524 let parsed_op = BitmaskOperator::from_byte_and_value(byte, 42).unwrap();
525 assert_eq!(parsed_op.value_length, expected_len);
526 }
527 }
528}