1use crate::dna::hel::error::HlxError;
14use crate::ops::utils;
15use crate::dna::atp::value::Value;
16use crate::ops::OperatorTrait;
17use async_trait::async_trait;
18use base64::{engine::general_purpose, Engine};
19use md5;
20use sha2::{Digest, Sha256};
21use std::collections::HashMap;
22
23pub struct StringOperators;
25
26impl StringOperators {
27 pub async fn new() -> Result<Self, HlxError> {
28 Ok(Self)
29 }
30
31 pub async fn execute(&self, operator: &str, params: &str) -> Result<Value, HlxError> {
32 self.execute_impl(operator, params).await
33 }
34
35 async fn execute_impl(&self, operator: &str, params: &str) -> Result<Value, HlxError> {
36 let params_map = crate::ops::utils::parse_params(params)?;
37
38 match operator {
39 "concat" => self.concat_operator(¶ms_map).await,
40 "split" => self.split_operator(¶ms_map).await,
41 "replace" => self.replace_operator(¶ms_map).await,
42 "trim" => self.trim_operator(¶ms_map).await,
43 "upper" => self.upper_operator(¶ms_map).await,
44 "lower" => self.lower_operator(¶ms_map).await,
45 "hash" => self.hash_operator(¶ms_map).await,
46 "format" => self.format_operator(¶ms_map).await,
47 _ => Err(HlxError::invalid_parameters(operator, "Unknown string operator")),
48 }
49 }
50}
51
52#[async_trait]
53impl crate::ops::OperatorTrait for StringOperators {
54 async fn execute(&self, operator: &str, params: &str) -> Result<Value, HlxError> {
55 self.execute_impl(operator, params).await
56 }
57}
58
59impl StringOperators {
60 async fn concat_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
61 let strings = params.get("strings")
62 .and_then(|v| v.as_array())
63 .ok_or_else(|| HlxError::validation_error("Missing 'strings' parameter", "Check the strings parameter"))?;
64
65 let separator = params.get("separator")
66 .and_then(|v| v.as_string())
67 .unwrap_or("");
68
69 let concatenated = strings.iter()
70 .map(|v| v.to_string())
71 .collect::<Vec<String>>()
72 .join(separator);
73
74 Ok(Value::Object({
75 let mut map = HashMap::new();
76 map.insert("result".to_string(), Value::String(concatenated.to_string()));
77 map.insert("count".to_string(), Value::Number(strings.len() as f64));
78 map.insert("separator".to_string(), Value::String(separator.to_string()));
79 map
80 }))
81 }
82
83 async fn split_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
84 let input = params.get("input")
85 .and_then(|v| v.as_string())
86 .ok_or_else(|| HlxError::validation_error("Missing 'input' parameter", "Check the input parameter"))?;
87
88 let delimiter = params.get("delimiter")
89 .and_then(|v| v.as_string())
90 .unwrap_or(" ");
91
92 let parts: Vec<Value> = input.split(delimiter)
93 .map(|s| Value::String(s.to_string()))
94 .collect();
95
96 Ok(Value::Object({
97 let mut map = HashMap::new();
98 map.insert("parts".to_string(), Value::Array(parts.clone()));
99 map.insert("count".to_string(), Value::Number(parts.len() as f64));
100 map.insert("delimiter".to_string(), Value::String(delimiter.to_string()));
101 map
102 }))
103 }
104
105 async fn replace_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
106 let input = params.get("input")
107 .and_then(|v| v.as_string())
108 .ok_or_else(|| HlxError::validation_error("Missing 'input' parameter", "Check the input parameter"))?;
109
110 let from = params.get("from")
111 .and_then(|v| v.as_string())
112 .ok_or_else(|| HlxError::validation_error("Missing 'from' parameter", "Check the from parameter"))?;
113
114 let to = params.get("to")
115 .and_then(|v| v.as_string())
116 .unwrap_or("");
117
118 let replaced = input.replace(from, &to);
119
120 Ok(Value::Object({
121 let mut map = HashMap::new();
122 map.insert("result".to_string(), Value::String(replaced.to_string()));
123 map.insert("original".to_string(), Value::String(input.to_string()));
124 map.insert("from".to_string(), Value::String(from.to_string()));
125 map.insert("to".to_string(), Value::String(to.to_string()));
126 map
127 }))
128 }
129
130 async fn trim_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
131 let input = params.get("input")
132 .and_then(|v| v.as_string())
133 .ok_or_else(|| HlxError::validation_error("Missing 'input' parameter", "Check the input parameter"))?;
134
135 let mode = params.get("mode")
136 .and_then(|v| v.as_string())
137 .unwrap_or("both");
138
139 let trimmed = match mode {
140 "left" => input.trim_start(),
141 "right" => input.trim_end(),
142 "both" => input.trim(),
143 _ => input.trim(),
144 };
145
146 Ok(Value::Object({
147 let mut map = HashMap::new();
148 map.insert("result".to_string(), Value::String(trimmed.to_string()));
149 map.insert("original".to_string(), Value::String(input.to_string()));
150 map.insert("mode".to_string(), Value::String(mode.to_string()));
151 map
152 }))
153 }
154
155 async fn upper_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
156 let input = params.get("input")
157 .and_then(|v| v.as_string())
158 .ok_or_else(|| HlxError::validation_error("Missing 'input' parameter", "Check the input parameter"))?;
159
160 let uppercased = input.to_uppercase();
161
162 Ok(Value::Object({
163 let mut map = HashMap::new();
164 map.insert("result".to_string(), Value::String(uppercased.to_string()));
165 map.insert("original".to_string(), Value::String(input.to_string()));
166 map.insert("operation".to_string(), Value::String("uppercase".to_string()));
167 map
168 }))
169 }
170
171 async fn lower_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
172 let input = params.get("input")
173 .and_then(|v| v.as_string())
174 .ok_or_else(|| HlxError::validation_error("Missing 'input' parameter", "Check the input parameter"))?;
175
176 let lowercased = input.to_lowercase();
177
178 Ok(Value::Object({
179 let mut map = HashMap::new();
180 map.insert("result".to_string(), Value::String(lowercased.to_string()));
181 map.insert("original".to_string(), Value::String(input.to_string()));
182 map.insert("operation".to_string(), Value::String("lowercase".to_string()));
183 map
184 }))
185 }
186
187 async fn hash_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
188 let input = params.get("input")
189 .and_then(|v| v.as_string())
190 .ok_or_else(|| HlxError::validation_error("Missing 'input' parameter", "Check the input parameter"))?;
191
192 let algorithm = params.get("algorithm")
193 .and_then(|v| v.as_string())
194 .unwrap_or("sha256");
195
196 let hash = match algorithm {
197 "sha256" => {
198 let mut hasher = Sha256::new();
199 hasher.update(input.as_bytes());
200 general_purpose::STANDARD.encode(hasher.finalize())
201 },
202 "md5" => {
203 let digest = md5::compute(input.as_bytes());
204 general_purpose::STANDARD.encode(&digest[..])
205 },
206 _ => return Err(HlxError::hash_error(format!("Unsupported algorithm: {}", algorithm), "Check the hash algorithm parameter")),
207 };
208
209 Ok(Value::Object({
210 let mut map = HashMap::new();
211 map.insert("hash".to_string(), Value::String(hash.to_string()));
212 map.insert("algorithm".to_string(), Value::String(algorithm.to_string()));
213 map.insert("input".to_string(), Value::String(input.to_string()));
214 map
215 }))
216 }
217
218 async fn format_operator(&self, params: &HashMap<String, Value>) -> Result<Value, HlxError> {
219 let template = params.get("template")
220 .and_then(|v| v.as_string())
221 .ok_or_else(|| HlxError::validation_error("Missing 'template' parameter", "Check the template parameter"))?;
222
223 let variables = params.get("variables")
224 .and_then(|v| v.as_object())
225 .cloned()
226 .unwrap_or_default();
227
228 let mut result = template.to_string();
229 for (key, value) in &variables {
230 let placeholder = format!("${{{}}}", key);
231 let value_str = value.to_string();
232 result = result.replace(&placeholder, &value_str);
233 }
234
235 Ok(Value::Object({
236 let mut map = HashMap::new();
237 map.insert("result".to_string(), Value::String(result.to_string()));
238 map.insert("template".to_string(), Value::String(template.to_string()));
239 map.insert("variables_used".to_string(), Value::Number(variables.len() as f64));
240 map
241 }))
242 }
243}