1use postrust_core::api_request::{
7 Field, Filter, LogicOperator, LogicTree, OpExpr, Operation, QuantOperator,
8};
9use serde::{Deserialize, Serialize};
10
11#[derive(Debug, Clone, Default, Serialize, Deserialize)]
13pub struct StringFilterInput {
14 pub eq: Option<String>,
16 pub neq: Option<String>,
18 pub like: Option<String>,
20 pub ilike: Option<String>,
22 #[serde(rename = "in")]
24 pub in_list: Option<Vec<String>>,
25 #[serde(rename = "isNull")]
27 pub is_null: Option<bool>,
28 #[serde(rename = "startsWith")]
30 pub starts_with: Option<String>,
31 #[serde(rename = "endsWith")]
33 pub ends_with: Option<String>,
34 pub contains: Option<String>,
36}
37
38impl StringFilterInput {
39 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
41 let mut filters = Vec::new();
42 let field = Field::simple(field_name);
43
44 if let Some(ref value) = self.eq {
45 filters.push(Filter::new(
46 field.clone(),
47 OpExpr::new(Operation::Quant {
48 op: QuantOperator::Equal,
49 quantifier: None,
50 value: value.clone(),
51 }),
52 ));
53 }
54
55 if let Some(ref value) = self.neq {
56 filters.push(Filter::new(
57 field.clone(),
58 OpExpr::new(Operation::Quant {
59 op: QuantOperator::Equal,
60 quantifier: None,
61 value: value.clone(),
62 })
63 .with_negated(true),
64 ));
65 }
66
67 if let Some(ref value) = self.like {
68 filters.push(Filter::new(
69 field.clone(),
70 OpExpr::new(Operation::Quant {
71 op: QuantOperator::Like,
72 quantifier: None,
73 value: value.clone(),
74 }),
75 ));
76 }
77
78 if let Some(ref value) = self.ilike {
79 filters.push(Filter::new(
80 field.clone(),
81 OpExpr::new(Operation::Quant {
82 op: QuantOperator::ILike,
83 quantifier: None,
84 value: value.clone(),
85 }),
86 ));
87 }
88
89 if let Some(ref values) = self.in_list {
90 filters.push(Filter::new(
91 field.clone(),
92 OpExpr::new(Operation::In(values.clone())),
93 ));
94 }
95
96 if let Some(is_null) = self.is_null {
97 let op_expr = OpExpr::new(Operation::Is(
98 postrust_core::api_request::IsValue::Null,
99 ));
100 filters.push(Filter::new(
101 field.clone(),
102 if is_null {
103 op_expr
104 } else {
105 op_expr.with_negated(true)
106 },
107 ));
108 }
109
110 if let Some(ref value) = self.starts_with {
111 filters.push(Filter::new(
112 field.clone(),
113 OpExpr::new(Operation::Quant {
114 op: QuantOperator::Like,
115 quantifier: None,
116 value: format!("{}%", value),
117 }),
118 ));
119 }
120
121 if let Some(ref value) = self.ends_with {
122 filters.push(Filter::new(
123 field.clone(),
124 OpExpr::new(Operation::Quant {
125 op: QuantOperator::Like,
126 quantifier: None,
127 value: format!("%{}", value),
128 }),
129 ));
130 }
131
132 if let Some(ref value) = self.contains {
133 filters.push(Filter::new(
134 field.clone(),
135 OpExpr::new(Operation::Quant {
136 op: QuantOperator::Like,
137 quantifier: None,
138 value: format!("%{}%", value),
139 }),
140 ));
141 }
142
143 filters
144 }
145
146 pub fn is_empty(&self) -> bool {
148 self.eq.is_none()
149 && self.neq.is_none()
150 && self.like.is_none()
151 && self.ilike.is_none()
152 && self.in_list.is_none()
153 && self.is_null.is_none()
154 && self.starts_with.is_none()
155 && self.ends_with.is_none()
156 && self.contains.is_none()
157 }
158}
159
160#[derive(Debug, Clone, Default, Serialize, Deserialize)]
162pub struct IntFilterInput {
163 pub eq: Option<i64>,
165 pub neq: Option<i64>,
167 pub gt: Option<i64>,
169 pub gte: Option<i64>,
171 pub lt: Option<i64>,
173 pub lte: Option<i64>,
175 #[serde(rename = "in")]
177 pub in_list: Option<Vec<i64>>,
178 #[serde(rename = "isNull")]
180 pub is_null: Option<bool>,
181}
182
183impl IntFilterInput {
184 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
186 let mut filters = Vec::new();
187 let field = Field::simple(field_name);
188
189 if let Some(value) = self.eq {
190 filters.push(Filter::new(
191 field.clone(),
192 OpExpr::new(Operation::Quant {
193 op: QuantOperator::Equal,
194 quantifier: None,
195 value: value.to_string(),
196 }),
197 ));
198 }
199
200 if let Some(value) = self.neq {
201 filters.push(Filter::new(
202 field.clone(),
203 OpExpr::new(Operation::Quant {
204 op: QuantOperator::Equal,
205 quantifier: None,
206 value: value.to_string(),
207 })
208 .with_negated(true),
209 ));
210 }
211
212 if let Some(value) = self.gt {
213 filters.push(Filter::new(
214 field.clone(),
215 OpExpr::new(Operation::Quant {
216 op: QuantOperator::GreaterThan,
217 quantifier: None,
218 value: value.to_string(),
219 }),
220 ));
221 }
222
223 if let Some(value) = self.gte {
224 filters.push(Filter::new(
225 field.clone(),
226 OpExpr::new(Operation::Quant {
227 op: QuantOperator::GreaterThanEqual,
228 quantifier: None,
229 value: value.to_string(),
230 }),
231 ));
232 }
233
234 if let Some(value) = self.lt {
235 filters.push(Filter::new(
236 field.clone(),
237 OpExpr::new(Operation::Quant {
238 op: QuantOperator::LessThan,
239 quantifier: None,
240 value: value.to_string(),
241 }),
242 ));
243 }
244
245 if let Some(value) = self.lte {
246 filters.push(Filter::new(
247 field.clone(),
248 OpExpr::new(Operation::Quant {
249 op: QuantOperator::LessThanEqual,
250 quantifier: None,
251 value: value.to_string(),
252 }),
253 ));
254 }
255
256 if let Some(ref values) = self.in_list {
257 filters.push(Filter::new(
258 field.clone(),
259 OpExpr::new(Operation::In(
260 values.iter().map(|v| v.to_string()).collect(),
261 )),
262 ));
263 }
264
265 if let Some(is_null) = self.is_null {
266 let op_expr = OpExpr::new(Operation::Is(
267 postrust_core::api_request::IsValue::Null,
268 ));
269 filters.push(Filter::new(
270 field.clone(),
271 if is_null {
272 op_expr
273 } else {
274 op_expr.with_negated(true)
275 },
276 ));
277 }
278
279 filters
280 }
281
282 pub fn is_empty(&self) -> bool {
284 self.eq.is_none()
285 && self.neq.is_none()
286 && self.gt.is_none()
287 && self.gte.is_none()
288 && self.lt.is_none()
289 && self.lte.is_none()
290 && self.in_list.is_none()
291 && self.is_null.is_none()
292 }
293}
294
295#[derive(Debug, Clone, Default, Serialize, Deserialize)]
297pub struct FloatFilterInput {
298 pub eq: Option<f64>,
300 pub neq: Option<f64>,
302 pub gt: Option<f64>,
304 pub gte: Option<f64>,
306 pub lt: Option<f64>,
308 pub lte: Option<f64>,
310 #[serde(rename = "isNull")]
312 pub is_null: Option<bool>,
313}
314
315impl FloatFilterInput {
316 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
318 let mut filters = Vec::new();
319 let field = Field::simple(field_name);
320
321 if let Some(value) = self.eq {
322 filters.push(Filter::new(
323 field.clone(),
324 OpExpr::new(Operation::Quant {
325 op: QuantOperator::Equal,
326 quantifier: None,
327 value: value.to_string(),
328 }),
329 ));
330 }
331
332 if let Some(value) = self.neq {
333 filters.push(Filter::new(
334 field.clone(),
335 OpExpr::new(Operation::Quant {
336 op: QuantOperator::Equal,
337 quantifier: None,
338 value: value.to_string(),
339 })
340 .with_negated(true),
341 ));
342 }
343
344 if let Some(value) = self.gt {
345 filters.push(Filter::new(
346 field.clone(),
347 OpExpr::new(Operation::Quant {
348 op: QuantOperator::GreaterThan,
349 quantifier: None,
350 value: value.to_string(),
351 }),
352 ));
353 }
354
355 if let Some(value) = self.gte {
356 filters.push(Filter::new(
357 field.clone(),
358 OpExpr::new(Operation::Quant {
359 op: QuantOperator::GreaterThanEqual,
360 quantifier: None,
361 value: value.to_string(),
362 }),
363 ));
364 }
365
366 if let Some(value) = self.lt {
367 filters.push(Filter::new(
368 field.clone(),
369 OpExpr::new(Operation::Quant {
370 op: QuantOperator::LessThan,
371 quantifier: None,
372 value: value.to_string(),
373 }),
374 ));
375 }
376
377 if let Some(value) = self.lte {
378 filters.push(Filter::new(
379 field.clone(),
380 OpExpr::new(Operation::Quant {
381 op: QuantOperator::LessThanEqual,
382 quantifier: None,
383 value: value.to_string(),
384 }),
385 ));
386 }
387
388 if let Some(is_null) = self.is_null {
389 let op_expr = OpExpr::new(Operation::Is(
390 postrust_core::api_request::IsValue::Null,
391 ));
392 filters.push(Filter::new(
393 field.clone(),
394 if is_null {
395 op_expr
396 } else {
397 op_expr.with_negated(true)
398 },
399 ));
400 }
401
402 filters
403 }
404
405 pub fn is_empty(&self) -> bool {
407 self.eq.is_none()
408 && self.neq.is_none()
409 && self.gt.is_none()
410 && self.gte.is_none()
411 && self.lt.is_none()
412 && self.lte.is_none()
413 && self.is_null.is_none()
414 }
415}
416
417#[derive(Debug, Clone, Default, Serialize, Deserialize)]
419pub struct BooleanFilterInput {
420 pub eq: Option<bool>,
422 #[serde(rename = "isNull")]
424 pub is_null: Option<bool>,
425}
426
427impl BooleanFilterInput {
428 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
430 let mut filters = Vec::new();
431 let field = Field::simple(field_name);
432
433 if let Some(value) = self.eq {
434 filters.push(Filter::new(
435 field.clone(),
436 OpExpr::new(Operation::Is(if value {
437 postrust_core::api_request::IsValue::True
438 } else {
439 postrust_core::api_request::IsValue::False
440 })),
441 ));
442 }
443
444 if let Some(is_null) = self.is_null {
445 let op_expr = OpExpr::new(Operation::Is(
446 postrust_core::api_request::IsValue::Null,
447 ));
448 filters.push(Filter::new(
449 field.clone(),
450 if is_null {
451 op_expr
452 } else {
453 op_expr.with_negated(true)
454 },
455 ));
456 }
457
458 filters
459 }
460
461 pub fn is_empty(&self) -> bool {
463 self.eq.is_none() && self.is_null.is_none()
464 }
465}
466
467#[derive(Debug, Clone, Default, Serialize, Deserialize)]
469pub struct UuidFilterInput {
470 pub eq: Option<String>,
472 pub neq: Option<String>,
474 #[serde(rename = "in")]
476 pub in_list: Option<Vec<String>>,
477 #[serde(rename = "isNull")]
479 pub is_null: Option<bool>,
480}
481
482impl UuidFilterInput {
483 pub fn to_filters(&self, field_name: &str) -> Vec<Filter> {
485 let mut filters = Vec::new();
486 let field = Field::simple(field_name);
487
488 if let Some(ref value) = self.eq {
489 filters.push(Filter::new(
490 field.clone(),
491 OpExpr::new(Operation::Quant {
492 op: QuantOperator::Equal,
493 quantifier: None,
494 value: value.clone(),
495 }),
496 ));
497 }
498
499 if let Some(ref value) = self.neq {
500 filters.push(Filter::new(
501 field.clone(),
502 OpExpr::new(Operation::Quant {
503 op: QuantOperator::Equal,
504 quantifier: None,
505 value: value.clone(),
506 })
507 .with_negated(true),
508 ));
509 }
510
511 if let Some(ref values) = self.in_list {
512 filters.push(Filter::new(
513 field.clone(),
514 OpExpr::new(Operation::In(values.clone())),
515 ));
516 }
517
518 if let Some(is_null) = self.is_null {
519 let op_expr = OpExpr::new(Operation::Is(
520 postrust_core::api_request::IsValue::Null,
521 ));
522 filters.push(Filter::new(
523 field.clone(),
524 if is_null {
525 op_expr
526 } else {
527 op_expr.with_negated(true)
528 },
529 ));
530 }
531
532 filters
533 }
534
535 pub fn is_empty(&self) -> bool {
537 self.eq.is_none()
538 && self.neq.is_none()
539 && self.in_list.is_none()
540 && self.is_null.is_none()
541 }
542}
543
544pub fn filters_to_logic_tree(filters: Vec<Filter>) -> Option<LogicTree> {
546 if filters.is_empty() {
547 return None;
548 }
549
550 if filters.len() == 1 {
551 return Some(LogicTree::Stmt(filters.into_iter().next().unwrap()));
552 }
553
554 Some(LogicTree::Expr {
555 negated: false,
556 op: LogicOperator::And,
557 children: filters.into_iter().map(LogicTree::Stmt).collect(),
558 })
559}
560
561pub fn combine_with_and(trees: Vec<LogicTree>) -> Option<LogicTree> {
563 if trees.is_empty() {
564 return None;
565 }
566
567 if trees.len() == 1 {
568 return Some(trees.into_iter().next().unwrap());
569 }
570
571 Some(LogicTree::Expr {
572 negated: false,
573 op: LogicOperator::And,
574 children: trees,
575 })
576}
577
578pub fn combine_with_or(trees: Vec<LogicTree>) -> Option<LogicTree> {
580 if trees.is_empty() {
581 return None;
582 }
583
584 if trees.len() == 1 {
585 return Some(trees.into_iter().next().unwrap());
586 }
587
588 Some(LogicTree::Expr {
589 negated: false,
590 op: LogicOperator::Or,
591 children: trees,
592 })
593}
594
595pub fn negate_tree(tree: LogicTree) -> LogicTree {
597 match tree {
598 LogicTree::Expr {
599 negated,
600 op,
601 children,
602 } => LogicTree::Expr {
603 negated: !negated,
604 op,
605 children,
606 },
607 LogicTree::Stmt(filter) => {
608 let negated_expr = OpExpr {
609 negated: !filter.op_expr.negated,
610 operation: filter.op_expr.operation,
611 };
612 LogicTree::Stmt(Filter::new(filter.field, negated_expr))
613 }
614 }
615}
616
617trait OpExprExt {
619 fn with_negated(self, negated: bool) -> Self;
620}
621
622impl OpExprExt for OpExpr {
623 fn with_negated(mut self, negated: bool) -> Self {
624 self.negated = negated;
625 self
626 }
627}
628
629#[cfg(test)]
630mod tests {
631 use super::*;
632 use pretty_assertions::assert_eq;
633
634 #[test]
639 fn test_string_filter_eq() {
640 let filter = StringFilterInput {
641 eq: Some("test".to_string()),
642 ..Default::default()
643 };
644
645 let filters = filter.to_filters("name");
646 assert_eq!(filters.len(), 1);
647 assert_eq!(filters[0].field.name, "name");
648
649 match &filters[0].op_expr.operation {
650 Operation::Quant { op, value, .. } => {
651 assert_eq!(*op, QuantOperator::Equal);
652 assert_eq!(value, "test");
653 }
654 _ => panic!("Expected Quant operation"),
655 }
656 assert!(!filters[0].op_expr.negated);
657 }
658
659 #[test]
660 fn test_string_filter_neq() {
661 let filter = StringFilterInput {
662 neq: Some("test".to_string()),
663 ..Default::default()
664 };
665
666 let filters = filter.to_filters("name");
667 assert_eq!(filters.len(), 1);
668
669 match &filters[0].op_expr.operation {
670 Operation::Quant { op, value, .. } => {
671 assert_eq!(*op, QuantOperator::Equal);
672 assert_eq!(value, "test");
673 }
674 _ => panic!("Expected Quant operation"),
675 }
676 assert!(filters[0].op_expr.negated);
677 }
678
679 #[test]
680 fn test_string_filter_like() {
681 let filter = StringFilterInput {
682 like: Some("%test%".to_string()),
683 ..Default::default()
684 };
685
686 let filters = filter.to_filters("name");
687 assert_eq!(filters.len(), 1);
688
689 match &filters[0].op_expr.operation {
690 Operation::Quant { op, value, .. } => {
691 assert_eq!(*op, QuantOperator::Like);
692 assert_eq!(value, "%test%");
693 }
694 _ => panic!("Expected Quant operation"),
695 }
696 }
697
698 #[test]
699 fn test_string_filter_ilike() {
700 let filter = StringFilterInput {
701 ilike: Some("%TEST%".to_string()),
702 ..Default::default()
703 };
704
705 let filters = filter.to_filters("name");
706 assert_eq!(filters.len(), 1);
707
708 match &filters[0].op_expr.operation {
709 Operation::Quant { op, value, .. } => {
710 assert_eq!(*op, QuantOperator::ILike);
711 assert_eq!(value, "%TEST%");
712 }
713 _ => panic!("Expected Quant operation"),
714 }
715 }
716
717 #[test]
718 fn test_string_filter_in() {
719 let filter = StringFilterInput {
720 in_list: Some(vec!["a".to_string(), "b".to_string(), "c".to_string()]),
721 ..Default::default()
722 };
723
724 let filters = filter.to_filters("status");
725 assert_eq!(filters.len(), 1);
726
727 match &filters[0].op_expr.operation {
728 Operation::In(values) => {
729 assert_eq!(values.len(), 3);
730 assert_eq!(values[0], "a");
731 assert_eq!(values[1], "b");
732 assert_eq!(values[2], "c");
733 }
734 _ => panic!("Expected In operation"),
735 }
736 }
737
738 #[test]
739 fn test_string_filter_is_null_true() {
740 let filter = StringFilterInput {
741 is_null: Some(true),
742 ..Default::default()
743 };
744
745 let filters = filter.to_filters("name");
746 assert_eq!(filters.len(), 1);
747
748 match &filters[0].op_expr.operation {
749 Operation::Is(postrust_core::api_request::IsValue::Null) => {}
750 _ => panic!("Expected Is Null operation"),
751 }
752 assert!(!filters[0].op_expr.negated);
753 }
754
755 #[test]
756 fn test_string_filter_is_null_false() {
757 let filter = StringFilterInput {
758 is_null: Some(false),
759 ..Default::default()
760 };
761
762 let filters = filter.to_filters("name");
763 assert_eq!(filters.len(), 1);
764
765 match &filters[0].op_expr.operation {
766 Operation::Is(postrust_core::api_request::IsValue::Null) => {}
767 _ => panic!("Expected Is Null operation"),
768 }
769 assert!(filters[0].op_expr.negated);
770 }
771
772 #[test]
773 fn test_string_filter_starts_with() {
774 let filter = StringFilterInput {
775 starts_with: Some("hello".to_string()),
776 ..Default::default()
777 };
778
779 let filters = filter.to_filters("name");
780 assert_eq!(filters.len(), 1);
781
782 match &filters[0].op_expr.operation {
783 Operation::Quant { op, value, .. } => {
784 assert_eq!(*op, QuantOperator::Like);
785 assert_eq!(value, "hello%");
786 }
787 _ => panic!("Expected Quant operation"),
788 }
789 }
790
791 #[test]
792 fn test_string_filter_ends_with() {
793 let filter = StringFilterInput {
794 ends_with: Some("world".to_string()),
795 ..Default::default()
796 };
797
798 let filters = filter.to_filters("name");
799 assert_eq!(filters.len(), 1);
800
801 match &filters[0].op_expr.operation {
802 Operation::Quant { op, value, .. } => {
803 assert_eq!(*op, QuantOperator::Like);
804 assert_eq!(value, "%world");
805 }
806 _ => panic!("Expected Quant operation"),
807 }
808 }
809
810 #[test]
811 fn test_string_filter_contains() {
812 let filter = StringFilterInput {
813 contains: Some("foo".to_string()),
814 ..Default::default()
815 };
816
817 let filters = filter.to_filters("name");
818 assert_eq!(filters.len(), 1);
819
820 match &filters[0].op_expr.operation {
821 Operation::Quant { op, value, .. } => {
822 assert_eq!(*op, QuantOperator::Like);
823 assert_eq!(value, "%foo%");
824 }
825 _ => panic!("Expected Quant operation"),
826 }
827 }
828
829 #[test]
830 fn test_string_filter_multiple() {
831 let filter = StringFilterInput {
832 eq: Some("test".to_string()),
833 starts_with: Some("t".to_string()),
834 ..Default::default()
835 };
836
837 let filters = filter.to_filters("name");
838 assert_eq!(filters.len(), 2);
839 }
840
841 #[test]
842 fn test_string_filter_is_empty() {
843 let filter = StringFilterInput::default();
844 assert!(filter.is_empty());
845
846 let filter = StringFilterInput {
847 eq: Some("test".to_string()),
848 ..Default::default()
849 };
850 assert!(!filter.is_empty());
851 }
852
853 #[test]
858 fn test_int_filter_eq() {
859 let filter = IntFilterInput {
860 eq: Some(42),
861 ..Default::default()
862 };
863
864 let filters = filter.to_filters("age");
865 assert_eq!(filters.len(), 1);
866
867 match &filters[0].op_expr.operation {
868 Operation::Quant { op, value, .. } => {
869 assert_eq!(*op, QuantOperator::Equal);
870 assert_eq!(value, "42");
871 }
872 _ => panic!("Expected Quant operation"),
873 }
874 }
875
876 #[test]
877 fn test_int_filter_neq() {
878 let filter = IntFilterInput {
879 neq: Some(42),
880 ..Default::default()
881 };
882
883 let filters = filter.to_filters("age");
884 assert_eq!(filters.len(), 1);
885 assert!(filters[0].op_expr.negated);
886 }
887
888 #[test]
889 fn test_int_filter_gt() {
890 let filter = IntFilterInput {
891 gt: Some(18),
892 ..Default::default()
893 };
894
895 let filters = filter.to_filters("age");
896 assert_eq!(filters.len(), 1);
897
898 match &filters[0].op_expr.operation {
899 Operation::Quant { op, value, .. } => {
900 assert_eq!(*op, QuantOperator::GreaterThan);
901 assert_eq!(value, "18");
902 }
903 _ => panic!("Expected Quant operation"),
904 }
905 }
906
907 #[test]
908 fn test_int_filter_gte() {
909 let filter = IntFilterInput {
910 gte: Some(18),
911 ..Default::default()
912 };
913
914 let filters = filter.to_filters("age");
915 assert_eq!(filters.len(), 1);
916
917 match &filters[0].op_expr.operation {
918 Operation::Quant { op, value, .. } => {
919 assert_eq!(*op, QuantOperator::GreaterThanEqual);
920 assert_eq!(value, "18");
921 }
922 _ => panic!("Expected Quant operation"),
923 }
924 }
925
926 #[test]
927 fn test_int_filter_lt() {
928 let filter = IntFilterInput {
929 lt: Some(65),
930 ..Default::default()
931 };
932
933 let filters = filter.to_filters("age");
934 assert_eq!(filters.len(), 1);
935
936 match &filters[0].op_expr.operation {
937 Operation::Quant { op, value, .. } => {
938 assert_eq!(*op, QuantOperator::LessThan);
939 assert_eq!(value, "65");
940 }
941 _ => panic!("Expected Quant operation"),
942 }
943 }
944
945 #[test]
946 fn test_int_filter_lte() {
947 let filter = IntFilterInput {
948 lte: Some(65),
949 ..Default::default()
950 };
951
952 let filters = filter.to_filters("age");
953 assert_eq!(filters.len(), 1);
954
955 match &filters[0].op_expr.operation {
956 Operation::Quant { op, value, .. } => {
957 assert_eq!(*op, QuantOperator::LessThanEqual);
958 assert_eq!(value, "65");
959 }
960 _ => panic!("Expected Quant operation"),
961 }
962 }
963
964 #[test]
965 fn test_int_filter_in() {
966 let filter = IntFilterInput {
967 in_list: Some(vec![1, 2, 3]),
968 ..Default::default()
969 };
970
971 let filters = filter.to_filters("id");
972 assert_eq!(filters.len(), 1);
973
974 match &filters[0].op_expr.operation {
975 Operation::In(values) => {
976 assert_eq!(values.len(), 3);
977 assert_eq!(values[0], "1");
978 assert_eq!(values[1], "2");
979 assert_eq!(values[2], "3");
980 }
981 _ => panic!("Expected In operation"),
982 }
983 }
984
985 #[test]
986 fn test_int_filter_range() {
987 let filter = IntFilterInput {
988 gte: Some(18),
989 lte: Some(65),
990 ..Default::default()
991 };
992
993 let filters = filter.to_filters("age");
994 assert_eq!(filters.len(), 2);
995 }
996
997 #[test]
998 fn test_int_filter_is_empty() {
999 let filter = IntFilterInput::default();
1000 assert!(filter.is_empty());
1001
1002 let filter = IntFilterInput {
1003 eq: Some(42),
1004 ..Default::default()
1005 };
1006 assert!(!filter.is_empty());
1007 }
1008
1009 #[test]
1014 fn test_boolean_filter_eq_true() {
1015 let filter = BooleanFilterInput {
1016 eq: Some(true),
1017 ..Default::default()
1018 };
1019
1020 let filters = filter.to_filters("active");
1021 assert_eq!(filters.len(), 1);
1022
1023 match &filters[0].op_expr.operation {
1024 Operation::Is(postrust_core::api_request::IsValue::True) => {}
1025 _ => panic!("Expected Is True operation"),
1026 }
1027 }
1028
1029 #[test]
1030 fn test_boolean_filter_eq_false() {
1031 let filter = BooleanFilterInput {
1032 eq: Some(false),
1033 ..Default::default()
1034 };
1035
1036 let filters = filter.to_filters("active");
1037 assert_eq!(filters.len(), 1);
1038
1039 match &filters[0].op_expr.operation {
1040 Operation::Is(postrust_core::api_request::IsValue::False) => {}
1041 _ => panic!("Expected Is False operation"),
1042 }
1043 }
1044
1045 #[test]
1046 fn test_boolean_filter_is_empty() {
1047 let filter = BooleanFilterInput::default();
1048 assert!(filter.is_empty());
1049
1050 let filter = BooleanFilterInput {
1051 eq: Some(true),
1052 ..Default::default()
1053 };
1054 assert!(!filter.is_empty());
1055 }
1056
1057 #[test]
1062 fn test_float_filter_eq() {
1063 let filter = FloatFilterInput {
1064 eq: Some(3.14),
1065 ..Default::default()
1066 };
1067
1068 let filters = filter.to_filters("price");
1069 assert_eq!(filters.len(), 1);
1070
1071 match &filters[0].op_expr.operation {
1072 Operation::Quant { op, value, .. } => {
1073 assert_eq!(*op, QuantOperator::Equal);
1074 assert_eq!(value, "3.14");
1075 }
1076 _ => panic!("Expected Quant operation"),
1077 }
1078 }
1079
1080 #[test]
1081 fn test_float_filter_gt() {
1082 let filter = FloatFilterInput {
1083 gt: Some(100.0),
1084 ..Default::default()
1085 };
1086
1087 let filters = filter.to_filters("price");
1088 assert_eq!(filters.len(), 1);
1089
1090 match &filters[0].op_expr.operation {
1091 Operation::Quant { op, value, .. } => {
1092 assert_eq!(*op, QuantOperator::GreaterThan);
1093 assert_eq!(value, "100");
1094 }
1095 _ => panic!("Expected Quant operation"),
1096 }
1097 }
1098
1099 #[test]
1100 fn test_float_filter_is_empty() {
1101 let filter = FloatFilterInput::default();
1102 assert!(filter.is_empty());
1103 }
1104
1105 #[test]
1110 fn test_uuid_filter_eq() {
1111 let filter = UuidFilterInput {
1112 eq: Some("550e8400-e29b-41d4-a716-446655440000".to_string()),
1113 ..Default::default()
1114 };
1115
1116 let filters = filter.to_filters("id");
1117 assert_eq!(filters.len(), 1);
1118
1119 match &filters[0].op_expr.operation {
1120 Operation::Quant { op, value, .. } => {
1121 assert_eq!(*op, QuantOperator::Equal);
1122 assert_eq!(value, "550e8400-e29b-41d4-a716-446655440000");
1123 }
1124 _ => panic!("Expected Quant operation"),
1125 }
1126 }
1127
1128 #[test]
1129 fn test_uuid_filter_in() {
1130 let filter = UuidFilterInput {
1131 in_list: Some(vec![
1132 "550e8400-e29b-41d4-a716-446655440000".to_string(),
1133 "550e8400-e29b-41d4-a716-446655440001".to_string(),
1134 ]),
1135 ..Default::default()
1136 };
1137
1138 let filters = filter.to_filters("id");
1139 assert_eq!(filters.len(), 1);
1140
1141 match &filters[0].op_expr.operation {
1142 Operation::In(values) => {
1143 assert_eq!(values.len(), 2);
1144 }
1145 _ => panic!("Expected In operation"),
1146 }
1147 }
1148
1149 #[test]
1150 fn test_uuid_filter_is_empty() {
1151 let filter = UuidFilterInput::default();
1152 assert!(filter.is_empty());
1153 }
1154
1155 #[test]
1160 fn test_filters_to_logic_tree_empty() {
1161 let tree = filters_to_logic_tree(vec![]);
1162 assert!(tree.is_none());
1163 }
1164
1165 #[test]
1166 fn test_filters_to_logic_tree_single() {
1167 let filter = Filter::new(
1168 Field::simple("name"),
1169 OpExpr::new(Operation::Quant {
1170 op: QuantOperator::Equal,
1171 quantifier: None,
1172 value: "test".to_string(),
1173 }),
1174 );
1175
1176 let tree = filters_to_logic_tree(vec![filter]).unwrap();
1177 match tree {
1178 LogicTree::Stmt(_) => {}
1179 _ => panic!("Expected Stmt for single filter"),
1180 }
1181 }
1182
1183 #[test]
1184 fn test_filters_to_logic_tree_multiple() {
1185 let filter1 = Filter::new(
1186 Field::simple("name"),
1187 OpExpr::new(Operation::Quant {
1188 op: QuantOperator::Equal,
1189 quantifier: None,
1190 value: "test".to_string(),
1191 }),
1192 );
1193 let filter2 = Filter::new(
1194 Field::simple("age"),
1195 OpExpr::new(Operation::Quant {
1196 op: QuantOperator::GreaterThan,
1197 quantifier: None,
1198 value: "18".to_string(),
1199 }),
1200 );
1201
1202 let tree = filters_to_logic_tree(vec![filter1, filter2]).unwrap();
1203 match tree {
1204 LogicTree::Expr { op, children, .. } => {
1205 assert_eq!(op, LogicOperator::And);
1206 assert_eq!(children.len(), 2);
1207 }
1208 _ => panic!("Expected Expr for multiple filters"),
1209 }
1210 }
1211
1212 #[test]
1213 fn test_combine_with_and() {
1214 let filter1 = Filter::new(
1215 Field::simple("a"),
1216 OpExpr::new(Operation::Quant {
1217 op: QuantOperator::Equal,
1218 quantifier: None,
1219 value: "1".to_string(),
1220 }),
1221 );
1222 let filter2 = Filter::new(
1223 Field::simple("b"),
1224 OpExpr::new(Operation::Quant {
1225 op: QuantOperator::Equal,
1226 quantifier: None,
1227 value: "2".to_string(),
1228 }),
1229 );
1230
1231 let tree1 = LogicTree::Stmt(filter1);
1232 let tree2 = LogicTree::Stmt(filter2);
1233
1234 let combined = combine_with_and(vec![tree1, tree2]).unwrap();
1235 match combined {
1236 LogicTree::Expr { op, children, .. } => {
1237 assert_eq!(op, LogicOperator::And);
1238 assert_eq!(children.len(), 2);
1239 }
1240 _ => panic!("Expected Expr"),
1241 }
1242 }
1243
1244 #[test]
1245 fn test_combine_with_or() {
1246 let filter1 = Filter::new(
1247 Field::simple("a"),
1248 OpExpr::new(Operation::Quant {
1249 op: QuantOperator::Equal,
1250 quantifier: None,
1251 value: "1".to_string(),
1252 }),
1253 );
1254 let filter2 = Filter::new(
1255 Field::simple("b"),
1256 OpExpr::new(Operation::Quant {
1257 op: QuantOperator::Equal,
1258 quantifier: None,
1259 value: "2".to_string(),
1260 }),
1261 );
1262
1263 let tree1 = LogicTree::Stmt(filter1);
1264 let tree2 = LogicTree::Stmt(filter2);
1265
1266 let combined = combine_with_or(vec![tree1, tree2]).unwrap();
1267 match combined {
1268 LogicTree::Expr { op, children, .. } => {
1269 assert_eq!(op, LogicOperator::Or);
1270 assert_eq!(children.len(), 2);
1271 }
1272 _ => panic!("Expected Expr"),
1273 }
1274 }
1275
1276 #[test]
1277 fn test_negate_tree_stmt() {
1278 let filter = Filter::new(
1279 Field::simple("a"),
1280 OpExpr::new(Operation::Quant {
1281 op: QuantOperator::Equal,
1282 quantifier: None,
1283 value: "1".to_string(),
1284 }),
1285 );
1286
1287 let tree = LogicTree::Stmt(filter);
1288 let negated = negate_tree(tree);
1289
1290 match negated {
1291 LogicTree::Stmt(f) => {
1292 assert!(f.op_expr.negated);
1293 }
1294 _ => panic!("Expected Stmt"),
1295 }
1296 }
1297
1298 #[test]
1299 fn test_negate_tree_expr() {
1300 let filter = Filter::new(
1301 Field::simple("a"),
1302 OpExpr::new(Operation::Quant {
1303 op: QuantOperator::Equal,
1304 quantifier: None,
1305 value: "1".to_string(),
1306 }),
1307 );
1308
1309 let tree = LogicTree::Expr {
1310 negated: false,
1311 op: LogicOperator::And,
1312 children: vec![LogicTree::Stmt(filter)],
1313 };
1314
1315 let negated = negate_tree(tree);
1316
1317 match negated {
1318 LogicTree::Expr { negated, .. } => {
1319 assert!(negated);
1320 }
1321 _ => panic!("Expected Expr"),
1322 }
1323 }
1324}