1use crate::evaluator::RuntimeError;
7use crate::value::Value;
8use num_traits::ToPrimitive;
9use std::collections::HashMap;
10
11pub fn json_parse(args: &[Value]) -> Result<Value, RuntimeError> {
37 if args.len() != 1 {
38 return Err(RuntimeError::WrongArity {
39 expected: 1,
40 got: args.len(),
41 });
42 }
43
44 let json_str = match &args[0] {
45 Value::String(s) => s,
46 other => {
47 return Err(RuntimeError::TypeErrorDetailed {
48 expected: "String".to_string(),
49 got: format!("{:?}", other),
50 })
51 }
52 };
53
54 let json_value: serde_json::Value = serde_json::from_str(json_str)
56 .map_err(|e| RuntimeError::CustomError(format!("JSON parse error: {}", e)))?;
57
58 json_to_value(&json_value)
60}
61
62pub fn json_stringify(args: &[Value]) -> Result<Value, RuntimeError> {
84 if args.is_empty() || args.len() > 2 {
85 return Err(RuntimeError::WrongArity {
86 expected: 1,
87 got: args.len(),
88 });
89 }
90
91 let value = &args[0];
92 let indent = if args.len() == 2 {
93 match &args[1] {
94 Value::Number(n) => *n as usize,
95 other => {
96 return Err(RuntimeError::TypeErrorDetailed {
97 expected: "Number".to_string(),
98 got: format!("{:?}", other),
99 })
100 }
101 }
102 } else {
103 0
104 };
105
106 let json_value = value_to_json(value)?;
108
109 let json_str = if indent > 0 {
111 serde_json::to_string_pretty(&json_value)
112 } else {
113 serde_json::to_string(&json_value)
114 }
115 .map_err(|e| RuntimeError::CustomError(format!("JSON stringify error: {}", e)))?;
116
117 Ok(Value::String(json_str))
118}
119
120fn json_to_value(json: &serde_json::Value) -> Result<Value, RuntimeError> {
122 match json {
123 serde_json::Value::Null => Ok(Value::Null),
124 serde_json::Value::Bool(b) => Ok(Value::Boolean(*b)),
125 serde_json::Value::Number(n) => {
126 if let Some(i) = n.as_i64() {
127 Ok(Value::Number(i as f64))
128 } else if let Some(u) = n.as_u64() {
129 Ok(Value::Number(u as f64))
130 } else if let Some(f) = n.as_f64() {
131 Ok(Value::Number(f))
132 } else {
133 Err(RuntimeError::CustomError("Invalid JSON number".to_string()))
134 }
135 }
136 serde_json::Value::String(s) => Ok(Value::String(s.clone())),
137 serde_json::Value::Array(arr) => {
138 let mut aether_arr = Vec::new();
139 for item in arr {
140 aether_arr.push(json_to_value(item)?);
141 }
142 Ok(Value::Array(aether_arr))
143 }
144 serde_json::Value::Object(obj) => {
145 let mut aether_dict = HashMap::new();
146 for (key, val) in obj {
147 aether_dict.insert(key.clone(), json_to_value(val)?);
148 }
149 Ok(Value::Dict(aether_dict))
150 }
151 }
152}
153
154fn value_to_json(value: &Value) -> Result<serde_json::Value, RuntimeError> {
156 match value {
157 Value::Null => Ok(serde_json::Value::Null),
158 Value::Boolean(b) => Ok(serde_json::Value::Bool(*b)),
159 Value::Number(n) => Ok(serde_json::json!(n)),
160 Value::String(s) => Ok(serde_json::Value::String(s.clone())),
161 Value::Array(arr) => {
162 let mut json_arr = Vec::new();
163 for item in arr {
164 json_arr.push(value_to_json(item)?);
165 }
166 Ok(serde_json::Value::Array(json_arr))
167 }
168 Value::Dict(dict) => {
169 let mut json_obj = serde_json::Map::new();
170 for (key, val) in dict {
171 json_obj.insert(key.clone(), value_to_json(val)?);
172 }
173 Ok(serde_json::Value::Object(json_obj))
174 }
175 Value::Fraction(f) => {
176 let float_val = f.numer().to_f64().unwrap_or(0.0) / f.denom().to_f64().unwrap_or(1.0);
178 Ok(serde_json::json!(float_val))
179 }
180 other => Err(RuntimeError::CustomError(format!(
181 "Cannot convert {:?} to JSON",
182 other
183 ))),
184 }
185}