use imbl::Vector;
use toml::{Table, Value};
use crate::{model::{Field, Graph, NodeRef, NOEXPORT_FIELD_ATTR}, runtime::{Num, Val, ValRef}};
pub(super) fn toml_value_from_node(graph: &Graph, node: &NodeRef) -> Table {
let mut map = Table::new();
if let Some(node) = node.node(graph) {
for (name, dref) in &node.data {
if let Some(field) = graph.get_stof_data::<Field>(dref) {
if !field.attributes.contains_key(NOEXPORT_FIELD_ATTR.as_str()) {
if let Some(value) = toml_value(graph, field.value.get()) {
map.insert(name.to_string(), value);
}
}
}
}
for child in &node.children {
if let Some(child) = child.node(graph) {
if child.is_field() && !child.attributes.contains_key(NOEXPORT_FIELD_ATTR.as_str()) {
if let Some(value) = toml_value(graph, Val::Obj(child.id.clone())) {
map.insert(child.name.to_string(), value);
}
}
}
}
}
map
}
pub(super) fn toml_value(graph: &Graph, val: Val) -> Option<Value> {
match val {
Val::Void |
Val::Null => None,
Val::Promise(..) => None,
Val::Bool(v) => Some(Value::Boolean(v)),
Val::Str(v) => Some(Value::String(v.to_string())),
Val::Prompt(v) => Some(Value::String(v.to_string())),
Val::Num(v) => {
match v {
Num::Int(v) => Some(Value::Integer(v)),
Num::Float(v) => Some(Value::Float(v)),
Num::Units(v, _) => Some(Value::Float(v)),
}
},
Val::Blob(blob) => {
let mut array = Vec::new();
for v in blob {
array.push(Value::Integer(v as i64));
}
Some(Value::Array(array))
},
Val::Fn(_dref) => None,
Val::Data(_dref) => None,
Val::List(vals) => Some(value_from_array(graph, vals)),
Val::Tup(vals) => Some(value_from_array(graph, vals)),
Val::Ver(..) => Some(Value::String(val.to_string())),
Val::Set(vals) => Some(value_from_array(graph, vals.into_iter().collect())),
Val::Obj(nref) => {
let map = toml_value_from_node(graph, &nref);
Some(Value::Table(map))
},
Val::Map(map) => {
let mut table = Table::new();
for (k, v) in map {
let key = k.read().to_string();
if let Some(value) = toml_value(graph, v.read().clone()) {
table.insert(key, value);
}
}
Some(Value::Table(table))
},
}
}
fn value_from_array(graph: &Graph, vals: Vector<ValRef<Val>>) -> Value {
let mut results: Vec<Value> = Vec::new();
for val in vals {
if let Some(value) = toml_value(graph, val.read().clone()) {
results.push(value);
}
}
Value::Array(results)
}