helix/dna/ops/
utils.rs

1use crate::dna::hel::error::HlxError;
2use crate::dna::atp::value::Value;
3use serde_json::Value as JsonValue;
4use std::collections::HashMap;
5
6pub fn parse_params(params: &str) -> Result<HashMap<String, Value>, HlxError> {
7    if params.is_empty() {
8        return Ok(HashMap::new());
9    }
10    
11    // Try JSON format first
12    let json_str = params.trim_matches('"').trim_matches('\'');
13    let json_str = json_str.replace("\\\"", "\"").replace("\\'", "'");
14    if let Ok(JsonValue::Object(obj)) = serde_json::from_str::<JsonValue>(&json_str) {
15        let mut map = HashMap::new();
16        for (k, v) in obj {
17            map.insert(k, json_value_to_value(&v));
18        }
19        return Ok(map);
20    }
21    
22    // Try key=value format
23    let mut map = HashMap::new();
24    for pair in params.split(',') {
25        let pair = pair.trim();
26        if let Some((key, value)) = pair.split_once('=') {
27            let key = key.trim();
28            let value = value.trim();
29            
30            // Try to parse as number
31            if let Ok(num) = value.parse::<f64>() {
32                map.insert(key.to_string(), Value::Number(num));
33            }
34            // Try to parse as boolean
35            else if value == "true" {
36                map.insert(key.to_string(), Value::Bool(true));
37            }
38            else if value == "false" {
39                map.insert(key.to_string(), Value::Bool(false));
40            }
41            // Default to string
42            else {
43                map.insert(key.to_string(), Value::String(value.to_string()));
44            }
45        }
46    }
47    
48    if map.is_empty() {
49        Err(HlxError::invalid_parameters("unknown", params))
50    } else {
51        Ok(map)
52    }
53}
54pub fn json_value_to_value(json_value: &JsonValue) -> Value {
55    match json_value {
56        JsonValue::String(s) => {
57            if s.is_empty() {
58                Value::String("".to_string())
59            } else {
60                Value::String(s.clone())
61            }
62        }
63        JsonValue::Number(n) => {
64            if let Some(f) = n.as_f64() {
65                Value::Number(f)
66            } else {
67                Value::String(n.to_string())
68            }
69        }
70        JsonValue::Bool(b) => Value::Bool(*b),
71        JsonValue::Array(arr) => {
72            let values: Vec<Value> = arr
73                .iter()
74                .map(|v| json_value_to_value(v))
75                .collect();
76            Value::Array(values)
77        }
78        JsonValue::Object(obj) => {
79            let mut map = HashMap::new();
80            for (k, v) in obj {
81                map.insert(k.clone(), json_value_to_value(v));
82            }
83            Value::Object(map)
84        }
85        JsonValue::Null => Value::Null,
86    }
87}
88pub fn value_to_json_value(value: &Value) -> JsonValue {
89    match value {
90        Value::String(s) => JsonValue::String(s.clone()),
91        Value::Number(n) => {
92            JsonValue::Number(
93                serde_json::Number::from_f64(*n)
94                    .unwrap_or_else(|| serde_json::Number::from(0)),
95            )
96        }
97        Value::Bool(b) => JsonValue::Bool(*b),
98        Value::Array(arr) => {
99            let values: Vec<JsonValue> = arr
100                .iter()
101                .map(|v| value_to_json_value(v))
102                .collect();
103            JsonValue::Array(values)
104        }
105        Value::Object(obj) => {
106            let mut map = serde_json::Map::new();
107            for (k, v) in obj {
108                map.insert(k.clone(), value_to_json_value(v));
109            }
110            JsonValue::Object(map)
111        }
112        Value::Null => JsonValue::Null,
113        Value::Duration(d) => JsonValue::String(format!("{} {:?}", d.value, d.unit)),
114        Value::Reference(r) => JsonValue::String(format!("@{}", r)),
115        Value::Identifier(i) => JsonValue::String(i.clone()),
116        _ => JsonValue::Null,
117    }
118}
119
120pub fn value_to_json(value: &Value) -> serde_json::Value {
121match value {
122    Value::String(s) => serde_json::Value::String(s.clone()),
123    Value::Number(n) => {
124        serde_json::Value::Number(
125            serde_json::Number::from_f64(*n)
126                .unwrap_or_else(|| serde_json::Number::from(0)),
127        )
128    }
129    Value::Bool(b) => serde_json::Value::Bool(*b),
130    Value::Array(arr) => {
131        serde_json::Value::Array(arr.iter().map(value_to_json).collect())
132    }
133    Value::Object(obj) => {
134        serde_json::Value::Object(
135            obj.iter().map(|(k, v)| (k.clone(), value_to_json(v))).collect(),
136        )
137    }
138    Value::Null => serde_json::Value::Null,
139    Value::Duration(d) => serde_json::Value::String(format!("{} {:?}", d.value, d.unit)),
140    Value::Reference(r) => serde_json::Value::String(format!("@{}", r)),
141    Value::Identifier(i) => serde_json::Value::String(i.clone()),
142}
143}
144pub fn json_to_value(json_value: &serde_json::Value) -> Value {
145match json_value {
146    serde_json::Value::String(s) => Value::String(s.clone()),
147    serde_json::Value::Number(n) => Value::Number(n.as_f64().unwrap_or(0.0)),
148    serde_json::Value::Bool(b) => Value::Bool(*b),
149    serde_json::Value::Array(arr) => {
150        Value::Array(arr.iter().map(json_to_value).collect())
151    }
152    serde_json::Value::Object(obj) => {
153        Value::Object(
154            obj.iter().map(|(k, v)| (k.clone(), json_to_value(v))).collect(),
155        )
156    }
157    serde_json::Value::Null => Value::Null,
158}
159}