capability_grower_configuration/fuzzy_from_json_value.rs
1// ---------------- [ File: capability-grower-configuration/src/fuzzy_from_json_value.rs ]
2crate::ix!();
3
4use serde_json::{Map, Value};
5use std::collections::{VecDeque, HashSet};
6
7/// Iteratively flattens all nested `"fields"` objects in this map (and any
8/// sub-objects), so that any key-value pairs inside `"fields"` get merged
9/// into the map that contains them. Avoids infinite recursion using
10/// BFS plus a pointer-based visited set.
11pub fn flatten_all_fields(obj: &mut Map<String, Value>) {
12 let mut queue = VecDeque::new();
13 let mut visited = HashSet::new();
14
15 // Start from the pointer to the initial object.
16 let root_ptr = (obj as *mut Map<String, Value>);
17 queue.push_back(root_ptr);
18
19 while let Some(obj_ptr) = queue.pop_front() {
20 // Convert raw pointer back to a mutable reference.
21 let current_map: &mut Map<String, Value> = unsafe { &mut *obj_ptr };
22
23 // If we’ve visited this particular Map before, skip it (avoids cycles).
24 let addr = obj_ptr as usize;
25 if !visited.insert(addr) {
26 continue;
27 }
28
29 // 1) Flatten this object’s "fields" if present.
30 if let Some(fields_val) = current_map.remove("fields") {
31 match fields_val {
32 Value::Object(mut fields_submap) => {
33 // Merge key/values from that fields_submap into current_map.
34 for (k, v) in fields_submap.iter() {
35 current_map.insert(k.to_string(), v.clone());
36 }
37 }
38 other => {
39 // If "fields" wasn’t an object, just restore it unchanged.
40 current_map.insert("fields".to_string(), other);
41 }
42 }
43 }
44
45 // 2) For every sub-value that’s an object, enqueue it for flattening too.
46 for val in current_map.values_mut() {
47 if let Value::Object(sub_obj) = val {
48 let sub_ptr = sub_obj as *mut Map<String, Value>;
49 queue.push_back(sub_ptr);
50 }
51 }
52 }
53}