1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
5pub enum StepCondition {
6 All(Vec<StepCondition>),
8 Any(Vec<StepCondition>),
10 None(Vec<StepCondition>),
12 OneOf(Vec<StepCondition>),
14 Not(Box<StepCondition>),
16 Comparison(FieldComparison),
18}
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
22pub struct FieldComparison {
23 pub field: String,
25 pub operator: ComparisonOp,
27 pub value: Option<serde_json::Value>,
29}
30
31#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
33pub enum ComparisonOp {
34 Equals,
35 NotEquals,
36 Gt,
37 Gte,
38 Lt,
39 Lte,
40 Contains,
41 IsNull,
42 IsNotNull,
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use pretty_assertions::assert_eq;
49 use serde_json::json;
50
51 #[test]
52 fn comparison_op_serde_round_trip() {
53 for op in [
54 ComparisonOp::Equals,
55 ComparisonOp::NotEquals,
56 ComparisonOp::Gt,
57 ComparisonOp::Gte,
58 ComparisonOp::Lt,
59 ComparisonOp::Lte,
60 ComparisonOp::Contains,
61 ComparisonOp::IsNull,
62 ComparisonOp::IsNotNull,
63 ] {
64 let json_str = serde_json::to_string(&op).unwrap();
65 let deserialized: ComparisonOp = serde_json::from_str(&json_str).unwrap();
66 assert_eq!(op, deserialized);
67 }
68 }
69
70 #[test]
71 fn field_comparison_serde_round_trip() {
72 let comp = FieldComparison {
73 field: ".outputs.status".to_string(),
74 operator: ComparisonOp::Equals,
75 value: Some(json!("success")),
76 };
77 let json_str = serde_json::to_string(&comp).unwrap();
78 let deserialized: FieldComparison = serde_json::from_str(&json_str).unwrap();
79 assert_eq!(comp, deserialized);
80 }
81
82 #[test]
83 fn field_comparison_without_value_serde_round_trip() {
84 let comp = FieldComparison {
85 field: ".outputs.result".to_string(),
86 operator: ComparisonOp::IsNull,
87 value: None,
88 };
89 let json_str = serde_json::to_string(&comp).unwrap();
90 let deserialized: FieldComparison = serde_json::from_str(&json_str).unwrap();
91 assert_eq!(comp, deserialized);
92 }
93
94 #[test]
95 fn step_condition_comparison_serde_round_trip() {
96 let condition = StepCondition::Comparison(FieldComparison {
97 field: ".count".to_string(),
98 operator: ComparisonOp::Gt,
99 value: Some(json!(5)),
100 });
101 let json_str = serde_json::to_string(&condition).unwrap();
102 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
103 assert_eq!(condition, deserialized);
104 }
105
106 #[test]
107 fn step_condition_not_serde_round_trip() {
108 let condition = StepCondition::Not(Box::new(StepCondition::Comparison(FieldComparison {
109 field: ".active".to_string(),
110 operator: ComparisonOp::Equals,
111 value: Some(json!(false)),
112 })));
113 let json_str = serde_json::to_string(&condition).unwrap();
114 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
115 assert_eq!(condition, deserialized);
116 }
117
118 #[test]
119 fn step_condition_all_serde_round_trip() {
120 let condition = StepCondition::All(vec![
121 StepCondition::Comparison(FieldComparison {
122 field: ".a".to_string(),
123 operator: ComparisonOp::Equals,
124 value: Some(json!(1)),
125 }),
126 StepCondition::Comparison(FieldComparison {
127 field: ".b".to_string(),
128 operator: ComparisonOp::Equals,
129 value: Some(json!(2)),
130 }),
131 ]);
132 let json_str = serde_json::to_string(&condition).unwrap();
133 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
134 assert_eq!(condition, deserialized);
135 }
136
137 #[test]
138 fn step_condition_any_serde_round_trip() {
139 let condition = StepCondition::Any(vec![StepCondition::Comparison(FieldComparison {
140 field: ".x".to_string(),
141 operator: ComparisonOp::IsNull,
142 value: None,
143 })]);
144 let json_str = serde_json::to_string(&condition).unwrap();
145 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
146 assert_eq!(condition, deserialized);
147 }
148
149 #[test]
150 fn step_condition_none_serde_round_trip() {
151 let condition = StepCondition::None(vec![StepCondition::Comparison(FieldComparison {
152 field: ".err".to_string(),
153 operator: ComparisonOp::IsNotNull,
154 value: None,
155 })]);
156 let json_str = serde_json::to_string(&condition).unwrap();
157 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
158 assert_eq!(condition, deserialized);
159 }
160
161 #[test]
162 fn step_condition_one_of_serde_round_trip() {
163 let condition = StepCondition::OneOf(vec![
164 StepCondition::Comparison(FieldComparison {
165 field: ".mode".to_string(),
166 operator: ComparisonOp::Equals,
167 value: Some(json!("fast")),
168 }),
169 StepCondition::Comparison(FieldComparison {
170 field: ".mode".to_string(),
171 operator: ComparisonOp::Equals,
172 value: Some(json!("slow")),
173 }),
174 ]);
175 let json_str = serde_json::to_string(&condition).unwrap();
176 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
177 assert_eq!(condition, deserialized);
178 }
179
180 #[test]
181 fn nested_combinator_serde_round_trip() {
182 let condition = StepCondition::All(vec![
183 StepCondition::Any(vec![
184 StepCondition::Comparison(FieldComparison {
185 field: ".a".to_string(),
186 operator: ComparisonOp::Equals,
187 value: Some(json!(1)),
188 }),
189 StepCondition::Comparison(FieldComparison {
190 field: ".b".to_string(),
191 operator: ComparisonOp::Equals,
192 value: Some(json!(2)),
193 }),
194 ]),
195 StepCondition::Not(Box::new(StepCondition::Comparison(FieldComparison {
196 field: ".c".to_string(),
197 operator: ComparisonOp::IsNull,
198 value: None,
199 }))),
200 ]);
201 let json_str = serde_json::to_string(&condition).unwrap();
202 let deserialized: StepCondition = serde_json::from_str(&json_str).unwrap();
203 assert_eq!(condition, deserialized);
204 }
205}