1use crate::dna::hel::error::HlxError;
12use crate::ops::utils;
13use crate::dna::atp::value::Value;
14use crate::ops::OperatorTrait;
15use async_trait::async_trait;
16use std::collections::HashMap;
17
18pub struct ConditionalOperators;
20
21impl ConditionalOperators {
22 pub async fn new() -> Result<Self, HlxError> {
23 Ok(Self)
24 }
25
26 pub async fn execute(&self, operator: &str, params: &str) -> Result<Value, HlxError> {
27 self.execute_impl(operator, params).await
28 }
29
30 async fn execute_impl(&self, operator: &str, params: &str) -> Result<Value, HlxError> {
31 let params_map = crate::ops::utils::parse_params(params)?;
32
33 match operator {
34 "if" => self.if_operator(¶ms_map).await,
35 "switch" => self.switch_operator(¶ms_map).await,
36 "loop" => self.loop_operator(¶ms_map).await,
37 "filter" => self.filter_operator(¶ms_map).await,
38 "map" => self.map_operator(¶ms_map).await,
39 "reduce" => self.reduce_operator(¶ms_map).await,
40 _ => Err(HlxError::invalid_parameters(&operator, "Unknown conditional operator")),
41 }
42 }
43}
44
45#[async_trait]
46impl crate::ops::OperatorTrait for ConditionalOperators {
47 async fn execute(&self, operator: &str, params: &str) -> Result<Value, HlxError> {
48 self.execute_impl(operator, params).await
49 }
50}
51
52impl ConditionalOperators {
53 async fn if_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
54 let condition = params.get("condition")
55 .ok_or_else(|| HlxError::validation_error("Missing 'condition' parameter", "Check the condition parameter"))?;
56
57 let then_value = params.get("then")
58 .ok_or_else(|| HlxError::validation_error("Missing 'then' parameter", "Check the then parameter"))?;
59
60 let else_value = params.get("else")
61 .cloned()
62 .unwrap_or(Value::Null);
63
64 let result = match condition {
65 Value::Bool(b) => {
66 if *b { then_value.clone() } else { else_value }
67 },
68 Value::String(s) => {
69 if !s.is_empty() { then_value.clone() } else { else_value }
70 },
71 Value::Number(n) => {
72 if *n != 0.0 { then_value.clone() } else { else_value }
73 },
74 Value::Array(arr) => {
75 if !arr.is_empty() { then_value.clone() } else { else_value }
76 },
77 Value::Object(obj) => {
78 if !obj.is_empty() { then_value.clone() } else { else_value }
79 },
80 _ => else_value,
81 };
82
83 Ok(Value::Object({
84 let mut map = HashMap::new();
85 map.insert("result".to_string(), result);
86 map.insert("condition_evaluated".to_string(), Value::Bool(true));
87 map
88 }))
89 }
90
91 async fn switch_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
92 let value = params.get("value")
93 .ok_or_else(|| HlxError::validation_error(
94 "Missing 'value' parameter", "Check the value parameter"
95 ))?;
96
97 let cases = params.get("cases")
98 .and_then(|v| v.as_object())
99 .ok_or_else(|| HlxError::validation_error(
100 "Missing or invalid 'cases' parameter", "Check the cases parameter"
101 ))?;
102
103 let default = params.get("default")
104 .cloned()
105 .unwrap_or(Value::Null);
106
107 let result = if let Some(case_value) = cases.get(&value.to_string()) {
108 case_value.clone()
109 } else {
110 default
111 };
112
113 Ok(Value::Object({
114 let mut map = HashMap::new();
115 map.insert("result".to_string(), result);
116 map.insert("matched_case".to_string(), value.clone());
117 map
118 }))
119 }
120
121 async fn loop_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
122 let iterations = params.get("iterations")
123 .and_then(|v| v.as_number())
124 .unwrap_or(1.0) as usize;
125
126 let action = params.get("action")
127 .and_then(|v| v.as_string())
128 .unwrap_or("default");
129
130 let mut results = Vec::new();
131 for i in 0..iterations {
132 results.push(Value::Object({
133 let mut map = HashMap::new();
134 map.insert("iteration".to_string(), Value::Number(i as f64));
135 map.insert("action".to_string(), Value::String(action.to_string()));
136 map.insert("completed".to_string(), Value::Bool(true));
137 map
138 }));
139 }
140
141 Ok(Value::Object({
142 let mut map = HashMap::new();
143 map.insert("iterations".to_string(), Value::Number(iterations as f64));
144 map.insert("results".to_string(), Value::Array(results));
145 map.insert("completed".to_string(), Value::Bool(true));
146 map
147 }))
148 }
149
150 async fn filter_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
151 let array = params.get("array")
152 .and_then(|v| v.as_array())
153 .ok_or_else(|| HlxError::validation_error(
154 "Missing 'array' parameter", "Check the array parameter"
155 ))?;
156
157 let predicate = params.get("predicate")
158 .and_then(|v| v.as_string())
159 .unwrap_or("all");
160
161 let filtered: Vec<Value> = match predicate {
162 "all" => array.to_vec(),
163 "non_null" => array.iter()
164 .filter(|item| !matches!(item, &Value::String(s) if s.is_empty()))
165 .cloned()
166 .collect(),
167 "non_empty" => array.iter()
168 .filter(|item| match item {
169 Value::String(s) => !s.is_empty(),
170 Value::Array(arr) => !arr.is_empty(),
171 Value::Object(obj) => !obj.is_empty(),
172 _ => true,
173 })
174 .cloned()
175 .collect(),
176 _ => array.to_vec(),
177 };
178
179 let filtered_count = filtered.len() as f64;
180
181 Ok(Value::Object({
182 let mut map = HashMap::new();
183 map.insert("filtered".to_string(), Value::Array(filtered));
184 map.insert("original_count".to_string(), Value::Number(array.len() as f64));
185 map.insert("filtered_count".to_string(), Value::Number(filtered_count));
186 map
187 }))
188 }
189
190 async fn map_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
191 let array = params.get("array")
192 .and_then(|v| v.as_array())
193 .ok_or_else(|| HlxError::validation_error(
194 "Missing 'array' parameter", "Check the array parameter"
195 ))?;
196
197 let transform = params.get("transform")
198 .and_then(|v| v.as_string())
199 .unwrap_or("identity");
200
201 let mapped: Vec<Value> = match transform {
202 "uppercase" => array.iter()
203 .map(|item| match item {
204 Value::String(s) => Value::String(s.to_uppercase()),
205 _ => item.clone(),
206 })
207 .collect(),
208 "lowercase" => array.iter()
209 .map(|item| match item {
210 Value::String(s) => Value::String(s.to_lowercase()),
211 _ => item.clone(),
212 })
213 .collect(),
214 "stringify" => array.iter()
215 .map(|item| Value::String(item.to_string()))
216 .collect(),
217 _ => array.to_vec(),
218 };
219
220 Ok(Value::Object({
221 let mut map = HashMap::new();
222 map.insert("mapped".to_string(), Value::Array(mapped.clone()));
223 map.insert("transform".to_string(), Value::String(transform.to_string()));
224 map.insert("count".to_string(), Value::Number(mapped.len() as f64));
225 map
226 }))
227 }
228
229 async fn reduce_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
230 let array = params.get("array")
231 .and_then(|v| v.as_array())
232 .ok_or_else(|| HlxError::validation_error(
233 "Missing 'array' parameter", "Check the array parameter"
234 ))?;
235
236 let operation = params.get("operation")
237 .and_then(|v| v.as_string())
238 .unwrap_or("sum");
239
240 let initial = params.get("initial")
241 .cloned()
242 .unwrap_or(Value::Number(0.0));
243
244 let result = match operation {
245 "sum" => {
246 let sum = array.iter()
247 .filter_map(|item| item.as_number())
248 .sum::<f64>();
249 Value::Number(sum)
250 },
251 "count" => Value::Number(array.len() as f64),
252 "join" => {
253 let joined = array.iter()
254 .map(|item| item.to_string())
255 .collect::<Vec<String>>()
256 .join("");
257 Value::String(joined)
258 },
259 "concat" => {
260 let mut result = Vec::new();
261 for item in array {
262 if let Value::Array(arr) = item {
263 result.extend_from_slice(arr);
264 } else {
265 result.push(item.clone());
266 }
267 }
268 Value::Array(result)
269 },
270 _ => initial,
271 };
272
273 Ok(Value::Object({
274 let mut map = HashMap::new();
275 map.insert("result".to_string(), result);
276 map.insert("operation".to_string(), Value::String(operation.to_string()));
277 map.insert("input_count".to_string(), Value::Number(array.len() as f64));
278 map
279 }))
280 }
281}