chiark / gitweb /
utils: Provide toml_merge
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 31 Jan 2021 16:45:43 +0000 (16:45 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 31 Jan 2021 18:38:28 +0000 (18:38 +0000)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/utils.rs

index 0980584d7dd71ea46e9889577469047a5154f052..ae8bffb6ad45b8ac0156292b5d85b8ea0bac612e 100644 (file)
@@ -141,3 +141,42 @@ impl<Y: Sync, E: Sync, F: Sync + FnOnce() -> Result<Y,E>>
 }
 
 // todo: DerefMut
+
+pub fn toml_merge<'u,
+                  S: 'u + AsRef<str>,
+                  KV: IntoIterator<Item=(&'u S, &'u toml::Value)>
+                  >(
+  table: &mut toml::value::Table,
+  updates: KV,
+) {
+  use toml::value::{Table, Value};
+  type TME<'e> = toml::map::Entry<'e>;
+
+  let mut kv = updates.into_iter().map(|(k, v)| (k.as_ref(), v));
+  inner(table, &mut kv);
+
+  fn inner<'u>(
+    table: &mut Table,
+    updates: &'u mut dyn Iterator<Item=(&'u str, &'u Value)>
+  ) {
+    for (k, v) in updates {
+      let e = table.entry(k);
+      match e {
+        TME::Vacant(ve) => {
+          ve.insert(v.clone());
+        }
+        TME::Occupied(mut oe) => match (oe.get_mut(), v) {
+          (Value::Table(old), Value::Table(new)) => {
+            toml_merge(old, new);
+          }
+          (Value::Array(old), Value::Array(new)) => {
+            old.extend(new.iter().cloned());
+          }
+          (old, new) => {
+            *old = new.clone();
+          }
+        }
+      }
+    }
+  }
+}