pub type Configuration = serde_json::Value;
pub(crate) trait Merge {
fn merge_overwrite(self, other: Self) -> Self;
}
impl Merge for Option<Configuration> {
fn merge_overwrite(self, other: Self) -> Self {
match (self, other) {
(None, None) => None,
(None, Some(other)) => Some(other),
(Some(s), None) => Some(s),
(Some(mut s), Some(mut other)) => {
if let (Some(s_obj), Some(o_obj)) = (s.as_object_mut(), other.as_object_mut()) {
o_obj.append(s_obj);
std::mem::swap(o_obj, s_obj);
} else {
log::warn!(
"Could not merge configurations: (1) < {} > with (2) < {} >. Keeping only (1).",
s,
other
);
}
Some(s)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde_json::json;
#[test]
fn test_merge_configurations() {
let global = Some(json!({ "a": { "nested": true }, "b": ["an", "array"] }));
let local = Some(json!({ "a": { "not-nested": false }, "c": 1 }));
assert_eq!(
global.clone().merge_overwrite(local.clone()),
Some(json!({ "a": { "nested": true }, "b": ["an", "array"], "c": 1 }))
);
assert_eq!(None.merge_overwrite(local.clone()), local);
assert_eq!(global.clone().merge_overwrite(None), global);
}
}