Skip to main content

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}