use serde_json::Value;
use crate::error::EvalError;
use super::{type_error, type_name};
pub fn eval_keys(value: &Value) -> Result<Value, EvalError> {
match value {
Value::Object(obj) => {
let mut keys: Vec<&String> = obj.keys().collect();
keys.sort(); let keys: Vec<Value> = keys.into_iter().map(|k| Value::String(k.clone())).collect();
Ok(Value::Array(keys))
}
Value::Array(arr) => {
let indices: Vec<Value> = (0..arr.len()).map(|i| Value::Number(i.into())).collect();
Ok(Value::Array(indices))
}
_ => Err(type_error(format!("{} has no keys", type_name(value)))),
}
}
pub fn eval_values(value: &Value) -> Result<Value, EvalError> {
match value {
Value::Object(obj) => {
let vals: Vec<Value> = obj.values().cloned().collect();
Ok(Value::Array(vals))
}
Value::Array(arr) => Ok(Value::Array(arr.clone())),
_ => Err(type_error(format!("{} has no values", type_name(value)))),
}
}
#[cfg(test)]
mod tests {
use crate::filter::builtins::{eval, Builtin};
use serde_json::json;
#[test]
fn test_keys_object() {
let result = eval(&Builtin::Keys, &json!({"b": 1, "a": 2, "c": 3})).unwrap();
assert_eq!(result, vec![json!(["a", "b", "c"])]); }
#[test]
fn test_keys_array() {
assert_eq!(eval(&Builtin::Keys, &json!([10, 20, 30])).unwrap(), vec![json!([0, 1, 2])]);
}
#[test]
fn test_keys_empty() {
assert_eq!(eval(&Builtin::Keys, &json!({})).unwrap(), vec![json!([])]);
assert_eq!(eval(&Builtin::Keys, &json!([])).unwrap(), vec![json!([])]);
}
#[test]
fn test_values_object() {
let result = eval(&Builtin::Values, &json!({"a": 1, "b": 2})).unwrap();
assert_eq!(result.len(), 1);
let arr = result[0].as_array().unwrap();
assert!(arr.contains(&json!(1)));
assert!(arr.contains(&json!(2)));
}
#[test]
fn test_values_array() {
assert_eq!(eval(&Builtin::Values, &json!([1, 2, 3])).unwrap(), vec![json!([1, 2, 3])]);
}
#[test]
fn test_keys_non_container_errors() {
assert!(eval(&Builtin::Keys, &json!("hello")).is_err());
assert!(eval(&Builtin::Keys, &json!(42)).is_err());
assert!(eval(&Builtin::Keys, &json!(null)).is_err());
}
}