fn merge_paths<T>(
    acc: &mut Map<String, JValue>,
    mut paths: Vec<(Vec<crate::Value>, T, isize)>,
    granularity: usize,
) -> Vec<Vec<String>>
where
    T: Timestamp + Lattice + std::convert::Into<Time>,
{
    use crate::Value;

    // `paths` has the structure `[[aid/eid val aid/eid val leaf-aid
    // leaf-val], ...]` Starting from the result map `acc`, for each
    // path, we want to navigate down the map, optionally creating
    // intermediate map levels if they don't exist yet, and finally
    // insert `leaf-val` at the lowest level.
    //
    // In short: We're rebuilding Clojure's `assoc-in` here:
    // `(assoc-in acc (pop path) (peek path))`

    // Keys have to be either aids (attributes on an entity)
    // or eids (nested entities). Both types will be converted
    // to strings.
    let parse_key = |v: Value| match v {
        Value::Aid(x) => x,
        Value::Eid(x) => x.to_string(),
        Value::String(x) => x,
        _ => panic!("Malformed pull path. Expected a key."),
    };

    // It's important to treat retractions first, otherwise we might
    // dissoc the new value.
    paths.sort_by_key(|(_path, _t, diff)| *diff);
    paths.sort_by_key(|(_path, t, _diff)| t.clone());

    let mut changes: Vec<Vec<String>> = Vec::new();

    for (mut path, _t, diff) in paths {
        let mut change_key: Vec<String> = Vec::new();

        let leaf_val: Value = path.pop().expect("leaf value missing");
        let leaf_key: String = parse_key(path.pop().expect("leaf keay missing"));

        if path.is_empty() {
            if change_key.len() < granularity {
                change_key.push(leaf_key.clone());
            }
            acc.insert(leaf_key, serde_json::Value::from(leaf_val));
        } else {
            let first_key = parse_key(path[0].clone());

            if change_key.len() < granularity {
                change_key.push(first_key.clone());
            }

            let mut entry = acc.entry(first_key).or_insert_with(|| Object(Map::new()));

            for key in path.drain(1..) {
                // If there are already values for the looked at attribute, we
                // obtain a reference to it. Otherwise, we create a new `Map`
                // and obtain a reference to it, which will be used in the
                // next iteration.  We repeat this process of traversing down
                // the map and optionally creating new map levels until we've
                // run out of intermediate attributes.

                if change_key.len() < granularity {
                    change_key.push(parse_key(key.clone()));
                }

                if let Object(map) = entry {
                    entry = map
                        .entry(parse_key(key))
                        .or_insert_with(|| Object(Map::new()));
                }
            }

            // At the lowest level, we finally insert the leaf value.
            if let Object(map) = entry {
                if diff > 0 {
                    map.insert(leaf_key, serde_json::Value::from(leaf_val));
                } else {
                    map.remove(&leaf_key);
                }
            }
        }

        changes.push(change_key);
    }

    changes.sort();
    changes.dedup();
    changes
}
/// Outbound direction: Transform the provided query result paths into
/// a GraphQL-like / JSONy nested value to be provided to the user.
Outbound direction: Transform the provided query result paths into
a GraphQL-like / JSONy nested value to be provided to the user.
Outbound direction : Transform the provided query result paths into a GraphQL - like / JSONy nested value to be provided to the user .
fn merge_paths<T>(
    acc: &mut Map<String, JValue>,
    mut paths: Vec<(Vec<crate::Value>, T, isize)>,
    granularity: usize,
) -> Vec<Vec<String>>
where
    T: Timestamp + Lattice + std::convert::Into<Time>,
{
    use crate::Value;
    // `paths` has the structure `[[aid/eid val aid/eid val leaf-aid
    // leaf-val], ...]` Starting from the result map `acc`, for each
    // path, we want to navigate down the map, optionally creating
    // intermediate map levels if they don't exist yet, and finally
    // insert `leaf-val` at the lowest level.
    //
    // In short: We're rebuilding Clojure's `assoc-in` here:
    // `(assoc-in acc (pop path) (peek path))`
    // Keys have to be either aids (attributes on an entity)
    // or eids (nested entities). Both types will be converted
    // to strings.
    let parse_key = |v: Value| match v {
        Value::Aid(x) => x,
        Value::Eid(x) => x.to_string(),
        Value::String(x) => x,
        _ => panic!("Malformed pull path. Expected a key."),
    };
    // It's important to treat retractions first, otherwise we might
    // dissoc the new value.
    paths.sort_by_key(|(_path, _t, diff)| *diff);
    paths.sort_by_key(|(_path, t, _diff)| t.clone());
    let mut changes: Vec<Vec<String>> = Vec::new();
    for (mut path, _t, diff) in paths {
        let mut change_key: Vec<String> = Vec::new();
        let leaf_val: Value = path.pop().expect("leaf value missing");
        let leaf_key: String = parse_key(path.pop().expect("leaf keay missing"));
        if path.is_empty() {
            if change_key.len() < granularity {
                change_key.push(leaf_key.clone());
            }
            acc.insert(leaf_key, serde_json::Value::from(leaf_val));
        } else {
            let first_key = parse_key(path[0].clone());
            if change_key.len() < granularity {
                change_key.push(first_key.clone());
            }
            let mut entry = acc.entry(first_key).or_insert_with(|| Object(Map::new()));
            for key in path.drain(1..) {
                // If there are already values for the looked at attribute, we
                // obtain a reference to it. Otherwise, we create a new `Map`
                // and obtain a reference to it, which will be used in the
                // next iteration.  We repeat this process of traversing down
                // the map and optionally creating new map levels until we've
                // run out of intermediate attributes.
                if change_key.len() < granularity {
                    change_key.push(parse_key(key.clone()));
                }
                if let Object(map) = entry {
                    entry = map
                        .entry(parse_key(key))
                        .or_insert_with(|| Object(Map::new()));
                }
            }
            // At the lowest level, we finally insert the leaf value.
            if let Object(map) = entry {
                if diff > 0 {
                    map.insert(leaf_key, serde_json::Value::from(leaf_val));
                } else {
                    map.remove(&leaf_key);
                }
            }
        }
        changes.push(change_key);
    }
    changes.sort();
    changes.dedup();
    changes
}
fn merge_paths < T > ( acc : & mut Map < String , JValue > , mut paths : Vec < ( Vec < crate :: Value > , T , isize ) > , granularity : usize , ) -> Vec < Vec < String > > where T : Timestamp + Lattice + std :: convert :: Into < Time > , { use crate :: Value ; // `paths` has the structure `[[aid/eid val aid/eid val leaf-aid // leaf-val], ...]` Starting from the result map `acc`, for each // path, we want to navigate down the map, optionally creating // intermediate map levels if they don't exist yet, and finally // insert `leaf-val` at the lowest level. // // In short: We're rebuilding Clojure's `assoc-in` here: // `(assoc-in acc (pop path) (peek path))` // Keys have to be either aids (attributes on an entity) // or eids (nested entities). Both types will be converted // to strings. let parse_key = | v : Value | match v { Value :: Aid ( x ) => x , Value :: Eid ( x ) => x . to_string ( ) , Value :: String ( x ) => x , _ => panic ! ( " " ) , } ; // It's important to treat retractions first, otherwise we might // dissoc the new value. paths . sort_by_key ( | ( _path , _t , diff ) | * diff ) ; paths . sort_by_key ( | ( _path , t , _diff ) | t . clone ( ) ) ; let mut changes : Vec < Vec < String > > = Vec :: new ( ) ; for ( mut path , _t , diff ) in paths { let mut change_key : Vec < String > = Vec :: new ( ) ; let leaf_val : Value = path . pop ( ) . expect ( " " ) ; let leaf_key : String = parse_key ( path . pop ( ) . expect ( " " ) ) ; if path . is_empty ( ) { if change_key . len ( ) < granularity { change_key . push ( leaf_key . clone ( ) ) ; } acc . insert ( leaf_key , serde_json :: Value :: from ( leaf_val ) ) ; } else { let first_key = parse_key ( path [ 0 ] . clone ( ) ) ; if change_key . len ( ) < granularity { change_key . push ( first_key . clone ( ) ) ; } let mut entry = acc . entry ( first_key ) . or_insert_with ( | | Object ( Map :: new ( ) ) ) ; for key in path . drain ( 1 .. ) { // If there are already values for the looked at attribute, we // obtain a reference to it. Otherwise, we create a new `Map` // and obtain a reference to it, which will be used in the // next iteration.  We repeat this process of traversing down // the map and optionally creating new map levels until we've // run out of intermediate attributes. if change_key . len ( ) < granularity { change_key . push ( parse_key ( key . clone ( ) ) ) ; } if let Object ( map ) = entry { entry = map . entry ( parse_key ( key ) ) . or_insert_with ( | | Object ( Map :: new ( ) ) ) ; } } // At the lowest level, we finally insert the leaf value. if let Object ( map ) = entry { if diff > 0 { map . insert ( leaf_key , serde_json :: Value :: from ( leaf_val ) ) ; } else { map . remove ( & leaf_key ) ; } } } changes . push ( change_key ) ; } changes . sort ( ) ; changes . dedup ( ) ; changes }
Outbound direction: Transform the provided query result paths into
a GraphQL-like / JSONy nested value to be provided to the user.
Outbound direction : Transform the provided query result paths into a GraphQL - like / JSONy nested value to be provided to the user .
acc
&mut Map<String, JValue>
paths
Vec<(Vec<crate::Value>, T, isize)>
granularity
usize
acc
&mut Map<String, JValue>
paths
Vec<(Vec<crate::Value>, T, isize)>
granularity
usize