use imbl::Vector;
use rustc_hash::FxHashMap;
use serde_json::{Map, Value};
use crate::{model::{Field, Graph, NodeRef, SId, NOEXPORT_FIELD_ATTR}, runtime::{Val, ValRef, Variable}};
pub(crate) fn parse_json_object_value(graph: &mut Graph, node: &NodeRef, value: Value) {
match value {
Value::Object(map) => {
for (field, val) in map {
let jf = parse_json_field_value(graph, node, val, &field);
graph.insert_stof_data(node, &field, Box::new(jf), None);
}
},
_ => {
let mut map = Map::new();
map.insert("field".into(), value);
parse_json_object_value(graph, node, Value::Object(map));
}
}
}
pub(crate) fn parse_json_field_value(graph: &mut Graph, node: &NodeRef, value: Value, field: &str) -> Field {
match value {
Value::Null => {
Field::new(Variable::new(graph, true, Val::Null, false), None)
},
Value::Number(v) => {
let val: Val;
if v.is_i64() {
val = v.as_i64().unwrap().into();
} else if v.is_u64() {
val = v.as_u64().unwrap().into();
} else if v.is_f64() {
val = v.as_f64().unwrap().into();
} else {
val = Val::Null
}
Field::new(Variable::new(graph, true, val, false), None)
},
Value::String(v) => {
Field::new(Variable::new(graph, true, Val::from(v.as_str()), false), None)
},
Value::Bool(v) => {
Field::new(Variable::new(graph, true, Val::from(v), false), None)
},
Value::Array(vals) => {
let mut jf_arr = Vector::default();
parse_json_array_values(graph, node, vals, &mut jf_arr);
Field::new(Variable::new(graph, true, Val::List(jf_arr), false), None)
}
Value::Object(_) => {
let child_node = graph.insert_node(field, Some(node.clone()), true);
parse_json_object_value(graph, &child_node, value);
let mut attrs = FxHashMap::default();
attrs.insert(NOEXPORT_FIELD_ATTR.to_string(), Val::Null); Field::new(Variable::new(graph, true, Val::Obj(child_node), false), Some(attrs))
},
}
}
pub(crate) fn parse_json_array_values(graph: &mut Graph, node: &NodeRef, vals: Vec<Value>, res: &mut Vector<ValRef<Val>>) {
for val in vals {
match val {
Value::Null => {
res.push_back(ValRef::new(Val::Null));
},
Value::Number(v) => {
let val: Val;
if v.is_i64() {
val = v.as_i64().unwrap().into();
} else if v.is_u64() {
val = v.as_u64().unwrap().into();
} else if v.is_f64() {
val = v.as_f64().unwrap().into();
} else {
val = Val::Null
}
res.push_back(ValRef::new(val));
},
Value::String(v) => {
res.push_back(ValRef::new(Val::from(v.as_str())));
},
Value::Bool(v) => {
res.push_back(ValRef::new(Val::from(v)));
},
Value::Array(vals) => {
let mut jf_arr = Vector::default();
parse_json_array_values(graph, node, vals, &mut jf_arr);
res.push_back(ValRef::new(Val::List(jf_arr)));
}
Value::Object(_) => {
let id = SId::default();
let child_node = graph.insert_node_id(&id, &id, Some(node.clone()), false);
parse_json_object_value(graph, &child_node, val);
res.push_back(ValRef::new(Val::Obj(child_node)));
},
}
}
}