Merge Layered TOML Configs
Recursively merge TOML tables so environment overlays change only the keys they declare while preserving sibling settings.
Code
use toml::Value;
fn merge(base: &mut Value, overlay: &Value) {
match (base, overlay) {
(Value::Table(base_map), Value::Table(overlay_map)) => {
for (key, value) in overlay_map {
match base_map.get_mut(key) {
Some(existing) => merge(existing, value),
None => {
base_map.insert(key.clone(), value.clone());
}
}
}
}
(base_slot, _) => {
*base_slot = overlay.clone();
}
}
}
fn main() -> Result<(), toml::de::Error> {
let base: Value = r#"
[server]
port = 8080
host = "127.0.0.1"
[server.tls]
enabled = false
"#
.parse()?;
let overlay: Value = r#"
[server]
port = 9090
[server.tls]
enabled = true
"#
.parse()?;
let mut merged = base;
merge(&mut merged, &overlay);
let rendered = toml::to_string(&merged).expect("serialize merged config");
println!("{rendered}");
Ok(())
}
Report a problem with this exampleOpens a pre-filled issue on GitHub.