use crate::list_override::{is_list_op_table, patch_value_list};
use toml::{Table, Value};
pub fn deep_merge(mut base: Table, overlay: Table) -> Table {
for (key, ov) in overlay {
match base.remove(&key) {
Some(Value::Table(bt)) => match ov {
Value::Table(ot) => {
base.insert(key, Value::Table(deep_merge(bt, ot)));
}
other => {
base.insert(key, other);
}
},
Some(Value::Array(ba)) if key == "presets" => {
if let Value::Array(oa) = ov {
base.insert(key, Value::Array(merge_presets(ba, oa)));
} else {
base.insert(key, ov);
}
}
Some(Value::Array(ba)) => match &ov {
Value::Table(t) if is_list_op_table(t) => {
let patched = patch_value_list(ba, &ov);
base.insert(key, Value::Array(patched));
}
_ => {
base.insert(key, ov);
}
},
_ => {
base.insert(key, ov);
}
}
}
base
}
pub fn merge_presets(mut base: Vec<Value>, overlay: Vec<Value>) -> Vec<Value> {
for ov in overlay {
let ov_id = preset_id(&ov);
match ov_id.and_then(|id| base.iter().position(|b| preset_id(b) == Some(id))) {
Some(pos) => base[pos] = ov,
None => base.push(ov),
}
}
base
}
fn preset_id(v: &Value) -> Option<&str> {
v.as_table()?.get("id")?.as_str()
}