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