merman_core/config/
mod.rs1use serde_json::{Map, Value};
2use std::sync::Arc;
3
4#[derive(Debug, Clone, PartialEq)]
5pub struct MermaidConfig(Arc<Value>);
6
7impl Default for MermaidConfig {
8 fn default() -> Self {
9 Self::empty_object()
10 }
11}
12
13impl MermaidConfig {
14 pub fn empty_object() -> Self {
15 Self(Arc::new(Value::Object(Map::new())))
16 }
17
18 pub fn from_value(value: Value) -> Self {
19 Self(Arc::new(value))
20 }
21
22 pub fn as_value(&self) -> &Value {
23 self.0.as_ref()
24 }
25
26 pub fn as_value_mut(&mut self) -> &mut Value {
27 Arc::make_mut(&mut self.0)
28 }
29
30 pub fn get_str(&self, dotted_path: &str) -> Option<&str> {
31 let mut cur: &Value = self.0.as_ref();
32 for segment in dotted_path.split('.') {
33 cur = cur.as_object()?.get(segment)?;
34 }
35 cur.as_str()
36 }
37
38 pub fn get_bool(&self, dotted_path: &str) -> Option<bool> {
39 let mut cur: &Value = self.0.as_ref();
40 for segment in dotted_path.split('.') {
41 cur = cur.as_object()?.get(segment)?;
42 }
43 cur.as_bool()
44 }
45
46 pub fn set_value(&mut self, dotted_path: &str, value: Value) {
47 let root_value = Arc::make_mut(&mut self.0);
48 if !root_value.is_object() {
52 *root_value = Value::Object(Map::new());
53 }
54
55 let Value::Object(root) = root_value else {
56 return;
57 };
58 let mut cur: &mut Map<String, Value> = root;
59 let mut segments = dotted_path.split('.').peekable();
60 while let Some(seg) = segments.next() {
61 if segments.peek().is_none() {
62 cur.insert(seg.to_string(), value);
63 return;
64 }
65 let slot = cur.entry(seg).or_insert_with(|| Value::Object(Map::new()));
66 if !slot.is_object() {
67 *slot = Value::Object(Map::new());
68 }
69 let Some(next) = slot.as_object_mut() else {
70 return;
71 };
72 cur = next;
73 }
74 }
75
76 pub fn deep_merge(&mut self, other: &Value) {
77 let Value::Object(m) = other else {
78 let base = Arc::make_mut(&mut self.0);
79 deep_merge_value(base, other);
80 return;
81 };
82 if m.is_empty() {
83 return;
84 }
85 let base = Arc::make_mut(&mut self.0);
86 deep_merge_value(base, other);
87 }
88}
89
90fn deep_merge_value(base: &mut Value, incoming: &Value) {
91 match (base, incoming) {
92 (Value::Object(base_map), Value::Object(in_map)) => {
93 for (key, in_value) in in_map {
94 match base_map.get_mut(key) {
95 Some(base_value) => deep_merge_value(base_value, in_value),
96 None => {
97 base_map.insert(key.clone(), in_value.clone());
98 }
99 }
100 }
101 }
102 (base_slot, in_value) => {
103 *base_slot = in_value.clone();
104 }
105 }
106}