custom_advance/
custom_advance.rs

1use datalogic_rs::arena::DataArena;
2use datalogic_rs::value::NumberValue;
3use datalogic_rs::{CustomOperator, DataLogic, DataValue, Result};
4use serde_json::json;
5use std::fmt::Debug;
6
7// Define a custom operator that multiplies all numbers in the array
8#[derive(Debug)]
9struct MultiplyAll;
10
11impl CustomOperator for MultiplyAll {
12    fn evaluate<'a>(
13        &self,
14        args: &'a [DataValue<'a>],
15        arena: &'a DataArena,
16    ) -> Result<&'a DataValue<'a>> {
17        // Default to 1 if no arguments provided
18        if args.is_empty() {
19            return Ok(arena.alloc(DataValue::Number(NumberValue::from_i64(1))));
20        }
21
22        // Calculate product of all numeric values
23        let mut product = 1.0;
24        for arg in args {
25            if let Some(n) = arg.as_f64() {
26                product *= n;
27            }
28        }
29
30        // Return the result
31        Ok(arena.alloc(DataValue::Number(NumberValue::from_f64(product))))
32    }
33}
34
35// Define a custom operator that returns the median of a set of numbers
36#[derive(Debug)]
37struct Median;
38
39impl CustomOperator for Median {
40    fn evaluate<'a>(
41        &self,
42        args: &'a [DataValue<'a>],
43        arena: &'a DataArena,
44    ) -> Result<&'a DataValue<'a>> {
45        // Collect all numeric values
46        let mut numbers = Vec::new();
47
48        // Handle the case where a single array is passed
49        if args.len() == 1 && args[0].is_array() {
50            if let Some(items) = args[0].as_array() {
51                for item in items {
52                    if let Some(n) = item.as_f64() {
53                        numbers.push(n);
54                    }
55                }
56            }
57        } else {
58            // Handle the case where multiple arguments are passed
59            for arg in args {
60                if let Some(n) = arg.as_f64() {
61                    numbers.push(n);
62                }
63            }
64        }
65
66        // Return 0 for empty arrays
67        if numbers.is_empty() {
68            return Ok(arena.alloc(DataValue::Number(NumberValue::from_i64(0))));
69        }
70
71        // Sort the numbers
72        numbers.sort_by(|a, b| a.partial_cmp(b).unwrap());
73
74        // Calculate the median
75        let median = if numbers.len() % 2 == 0 {
76            // Even number of elements - average the middle two
77            let mid = numbers.len() / 2;
78            (numbers[mid - 1] + numbers[mid]) / 2.0
79        } else {
80            // Odd number of elements - take the middle one
81            numbers[numbers.len() / 2]
82        };
83
84        // Return the result
85        Ok(arena.alloc(DataValue::Number(NumberValue::from_f64(median))))
86    }
87}
88
89fn main() {
90    let mut dl = DataLogic::new();
91
92    // Register custom operators
93    dl.register_custom_operator("multiply_all", Box::new(MultiplyAll));
94    dl.register_custom_operator("median", Box::new(Median));
95
96    // Example 1: Multiply numbers
97    let result = dl
98        .evaluate_str(r#"{"multiply_all": [2, 3, 4]}"#, r#"{}"#, None)
99        .unwrap();
100
101    println!("Product of [2, 3, 4] = {}", result);
102
103    // Example 2: Find median of a set of numbers
104    let result = dl
105        .evaluate_json(&json!({"median": [7, 3, 5, 9, 1]}), &json!({}), None)
106        .unwrap();
107
108    println!("Median of [7, 3, 5, 9, 1] = {}", result);
109
110    // Example 3: Use custom operators in a complex logic expression
111    let complex_logic = json!({
112        "if": [
113            {"<": [{"var": "score"}, 60]},
114            "Failed",
115            {">=": [{"var": "score"}, {"median": {"var": "class_scores"}}]},
116            "Above average",
117            "Below average"
118        ]
119    });
120
121    let data = json!({
122        "score": 75,
123        "class_scores": [60, 70, 80, 90, 100]
124    });
125
126    let result = dl.evaluate_json(&complex_logic, &data, None).unwrap();
127    println!("Student result: {}", result);
128
129    // Example 4: Combine custom operators
130    let combined_logic = json!({
131        "multiply_all": [
132            2,
133            {"median": [1, 2, 3, 4, 5]},
134            4
135        ]
136    });
137
138    let result = dl.evaluate_json(&combined_logic, &json!({}), None).unwrap();
139    println!("2 * median([1, 2, 3, 4, 5]) * 4 = {}", result);
140}