Skip to main content

atom_engine/filters/
system.rs

1use serde_json::{json, Value};
2use std::collections::HashMap;
3use std::sync::atomic::{AtomicUsize, Ordering};
4use tera::{Error, Function};
5
6use super::FilterResult;
7
8pub struct DumpFn;
9
10impl Function for DumpFn {
11    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
12        for (key, value) in args {
13            eprintln!("[dump] {} = {:?}", key, value);
14        }
15        Ok(Value::Null)
16    }
17}
18
19pub struct LogFn;
20
21impl Function for LogFn {
22    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
23        for (key, value) in args {
24            eprintln!("[log] {} = {:?}", key, value);
25        }
26        Ok(Value::Null)
27    }
28}
29
30pub struct RangeFn;
31
32impl Function for RangeFn {
33    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
34        let end = args
35            .get("end")
36            .and_then(|v| v.as_i64())
37            .ok_or_else(|| Error::msg("Missing 'end' argument"))?;
38        let start = args.get("start").and_then(|v| v.as_i64()).unwrap_or(0);
39        let step = args.get("step_by").and_then(|v| v.as_i64()).unwrap_or(1);
40
41        let result: Vec<Value> = (start..end)
42            .step_by(step as usize)
43            .map(|i| json!(i))
44            .collect();
45        Ok(Value::Array(result))
46    }
47}
48
49pub struct NowFn;
50
51impl Function for NowFn {
52    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
53        use chrono::Utc;
54        let _utc = args.get("utc").and_then(|v| v.as_bool()).unwrap_or(false);
55        let timestamp = args
56            .get("timestamp")
57            .and_then(|v| v.as_bool())
58            .unwrap_or(false);
59
60        if timestamp {
61            let now = Utc::now();
62            Ok(json!(now.timestamp()))
63        } else {
64            let now = Utc::now();
65            Ok(Value::String(now.to_rfc3339()))
66        }
67    }
68}
69
70pub struct CycleFn {
71    index: AtomicUsize,
72}
73
74impl CycleFn {
75    pub fn new() -> Self {
76        CycleFn {
77            index: AtomicUsize::new(0),
78        }
79    }
80}
81
82impl Default for CycleFn {
83    fn default() -> Self {
84        Self::new()
85    }
86}
87
88impl Function for CycleFn {
89    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
90        let values: Vec<Value> = (0..)
91            .map(|i| args.get(&format!("{}", i)))
92            .take_while(|v| v.is_some())
93            .map(|v| v.unwrap().clone())
94            .collect();
95        if values.is_empty() {
96            return Ok(Value::Null);
97        }
98        let idx = self.index.fetch_add(1, Ordering::SeqCst) % values.len();
99        Ok(values[idx].clone())
100    }
101}
102
103pub struct UuidFn;
104
105impl Function for UuidFn {
106    fn call(&self, _: &HashMap<String, Value>) -> FilterResult {
107        Ok(Value::String(uuid::Uuid::new_v4().to_string()))
108    }
109}
110
111pub struct RandomFn;
112
113impl Function for RandomFn {
114    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
115        use rand::Rng;
116        let mut rng = rand::thread_rng();
117        let min = args.get("min").and_then(|v| v.as_i64()).unwrap_or(0);
118        let max = args.get("max").and_then(|v| v.as_i64()).unwrap_or(100);
119        let result = rng.gen_range(min..=max);
120        Ok(Value::Number(result.into()))
121    }
122}
123
124pub struct ChoiceFn;
125
126impl Function for ChoiceFn {
127    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
128        use rand::seq::SliceRandom;
129        use rand::thread_rng;
130        let array = args
131            .get("array")
132            .ok_or_else(|| Error::msg("Missing array"))?;
133        let arr = array
134            .as_array()
135            .ok_or_else(|| Error::msg("Expected array"))?;
136        if arr.is_empty() {
137            return Ok(Value::Null);
138        }
139        let mut rng = thread_rng();
140        let choice = arr.choose(&mut rng).cloned();
141        Ok(choice.unwrap_or(Value::Null))
142    }
143}
144
145pub struct FileExistsFn;
146
147impl Function for FileExistsFn {
148    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
149        let path = args.get("path").and_then(|v| v.as_str()).unwrap_or("");
150        Ok(Value::Bool(std::path::Path::new(path).exists()))
151    }
152}
153
154pub struct EnvFn;
155
156impl Function for EnvFn {
157    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
158        let key = args.get("key").and_then(|v| v.as_str()).unwrap_or("");
159        Ok(Value::String(std::env::var(key).unwrap_or_default()))
160    }
161}
162
163pub struct Md5Fn;
164
165impl Function for Md5Fn {
166    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
167        use md5::{Digest, Md5};
168        let input = args.get("string").and_then(|v| v.as_str()).unwrap_or("");
169        let result = Md5::digest(input);
170        Ok(Value::String(hex::encode(result)))
171    }
172}
173
174pub struct Sha256Fn;
175
176impl Function for Sha256Fn {
177    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
178        use sha2::{Digest, Sha256};
179        let input = args.get("string").and_then(|v| v.as_str()).unwrap_or("");
180        let result = Sha256::digest(input);
181        Ok(Value::String(hex::encode(result)))
182    }
183}
184
185pub struct RepeatFn;
186
187impl Function for RepeatFn {
188    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
189        let count = args.get("count").and_then(|v| v.as_u64()).unwrap_or(1) as usize;
190        let content = args.get("content").and_then(|v| v.as_str()).unwrap_or("");
191        let separator = args.get("separator").and_then(|v| v.as_str()).unwrap_or("");
192
193        let result: Vec<String> = (0..count).map(|_| content.to_string()).collect();
194        Ok(Value::String(result.join(separator)))
195    }
196}
197
198pub struct TimesFn;
199
200impl Function for TimesFn {
201    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
202        let times = args.get("times").and_then(|v| v.as_u64()).unwrap_or(1) as usize;
203        let start = args.get("start").and_then(|v| v.as_i64()).unwrap_or(1);
204        let step = args.get("step").and_then(|v| v.as_i64()).unwrap_or(1);
205
206        let result: Vec<Value> = (0..times)
207            .map(|i| json!(start + (i as i64) * step))
208            .collect();
209        Ok(Value::Array(result))
210    }
211}
212
213pub struct LoopFn;
214
215impl Function for LoopFn {
216    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
217        let from = args.get("from").and_then(|v| v.as_i64()).unwrap_or(0);
218        let to = args.get("to").and_then(|v| v.as_i64()).unwrap_or(10);
219        let step = args.get("step").and_then(|v| v.as_i64()).unwrap_or(1);
220        let include = args
221            .get("inclusive")
222            .and_then(|v| v.as_bool())
223            .unwrap_or(false);
224
225        let end = if include { to + 1 } else { to };
226
227        let result: Vec<Value> = (from..end)
228            .step_by(step as usize)
229            .map(|i| json!({"index": i, "value": i}))
230            .collect();
231        Ok(Value::Array(result))
232    }
233}
234
235pub struct IterateFn;
236
237impl Function for IterateFn {
238    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
239        let array = args
240            .get("array")
241            .ok_or_else(|| Error::msg("Missing array"))?;
242        let arr = array
243            .as_array()
244            .ok_or_else(|| Error::msg("Expected array"))?;
245        let limit = args.get("limit").and_then(|v| v.as_u64()).unwrap_or(0) as usize;
246        let skip = args.get("skip").and_then(|v| v.as_u64()).unwrap_or(0) as usize;
247
248        let iter: Vec<Value> = arr
249            .iter()
250            .skip(skip)
251            .take(if limit > 0 { limit } else { arr.len() })
252            .enumerate()
253            .map(|(i, v)| serde_json::json!({"index": i, "value": v, "key": i}))
254            .collect();
255        Ok(Value::Array(iter))
256    }
257}
258
259pub struct ObjectFn;
260
261impl Function for ObjectFn {
262    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
263        let keys = args
264            .get("keys")
265            .and_then(|v| v.as_array())
266            .cloned()
267            .unwrap_or_default();
268        let values = args
269            .get("values")
270            .and_then(|v| v.as_array())
271            .cloned()
272            .unwrap_or_default();
273
274        let mut obj = serde_json::Map::new();
275        for (i, key) in keys.iter().enumerate() {
276            if let Some(k) = key.as_str() {
277                let v = values.get(i).cloned().unwrap_or(Value::Null);
278                obj.insert(k.to_string(), v);
279            }
280        }
281        Ok(Value::Object(obj))
282    }
283}
284
285pub struct MergeFn;
286
287impl Function for MergeFn {
288    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
289        let arr1 = args
290            .get("array1")
291            .and_then(|v| v.as_array())
292            .cloned()
293            .unwrap_or_default();
294        let arr2 = args
295            .get("array2")
296            .and_then(|v| v.as_array())
297            .cloned()
298            .unwrap_or_default();
299
300        let mut result = arr1;
301        result.extend(arr2);
302        Ok(Value::Array(result))
303    }
304}
305
306pub struct ChunkFn;
307
308impl Function for ChunkFn {
309    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
310        let array = args
311            .get("array")
312            .ok_or_else(|| Error::msg("Missing array"))?;
313        let arr = array
314            .as_array()
315            .ok_or_else(|| Error::msg("Expected array"))?;
316        let size = args.get("size").and_then(|v| v.as_u64()).unwrap_or(2) as usize;
317
318        let chunks: Vec<Value> = arr
319            .chunks(size)
320            .map(|chunk| Value::Array(chunk.to_vec()))
321            .collect();
322        Ok(Value::Array(chunks))
323    }
324}
325
326pub struct ZipFn;
327
328impl Function for ZipFn {
329    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
330        let arrays = args
331            .get("arrays")
332            .and_then(|v| v.as_array())
333            .cloned()
334            .unwrap_or_default();
335
336        if arrays.is_empty() {
337            return Ok(Value::Array(Vec::new()));
338        }
339
340        let max_len = arrays
341            .iter()
342            .map(|a| a.as_array().map(|a| a.len()).unwrap_or(0))
343            .max()
344            .unwrap_or(0);
345
346        let result: Vec<Value> = (0..max_len)
347            .map(|i| {
348                let items: Vec<Value> = arrays
349                    .iter()
350                    .filter_map(|a| a.as_array().and_then(|arr| arr.get(i).cloned()))
351                    .collect();
352                Value::Array(items)
353            })
354            .collect();
355        Ok(Value::Array(result))
356    }
357}
358
359pub struct CompactFn;
360
361impl Function for CompactFn {
362    fn call(&self, args: &HashMap<String, Value>) -> FilterResult {
363        let array = args
364            .get("array")
365            .ok_or_else(|| Error::msg("Missing array"))?;
366        let arr = array
367            .as_array()
368            .ok_or_else(|| Error::msg("Expected array"))?;
369
370        let result: Vec<Value> = arr
371            .iter()
372            .filter(|v| !v.is_null() && !v.as_array().map(|a| a.is_empty()).unwrap_or(false))
373            .cloned()
374            .collect();
375        Ok(Value::Array(result))
376    }
377}