dagre_rust 0.0.5

Dagre implementation in Rust
Documentation
use graphlib_rust::Graph;
use ordered_hashmap::OrderedHashMap;
use crate::{GraphConfig, GraphEdge, GraphNode};
use crate::layout::order::barycenter::{barycenter, Barycenter};
use crate::layout::order::resolve_conflicts::{resolve_conflicts, ResolvedBaryEntry};
use crate::layout::order::sort::sort;

#[derive(Debug, Clone, Default)]
pub struct SubgraphResult {
  pub vs: Vec<String>,
  pub barycenter: f32,
  pub weight: f32
}

pub fn sort_subgraph(
  g: &Graph<GraphConfig, GraphNode, GraphEdge>,
  v: &String,
  cg: &Graph<GraphConfig, GraphNode,GraphEdge>,
  bias_right: &bool
) -> SubgraphResult {
  let mut movable = g.children(v);
  let node = g.node(v);
  let bl = if node.is_some() {
    node.unwrap().border_left_.clone()
  } else {
    None
  };
  let br = if node.is_some() {
    node.unwrap().border_right_.clone()
  } else {
    None
  };
  let mut subgraphs: OrderedHashMap<String, SubgraphResult> = OrderedHashMap::new();

  if br.is_some() {
    movable = movable.into_iter().filter(|w| {
      w != &bl.clone().unwrap() && w != &br.clone().unwrap()
    }).collect();
  }

  let mut barycenters = barycenter(g, &movable);
  barycenters.iter_mut().for_each(|entry| {
    if g.children(&entry.v).len() > 0 {
      let subgraph_result = sort_subgraph(g, &entry.v, cg, bias_right);
      subgraphs.insert(entry.v.clone(), subgraph_result.clone());
      merge_barycenters(entry, &subgraph_result);
    }
  });

  let mut entries = resolve_conflicts(&barycenters, cg);
  expand_subgraphs(&mut entries, &subgraphs);

  let mut result = sort(&entries, bias_right);
  if bl.is_some() {
    let bl_ = bl.clone().unwrap();
    let br_ = br.clone().unwrap();
    result.vs = vec![vec![bl_.clone()], result.vs.clone(), vec![br_.clone()]].concat();
    let bl_preds = g.predecessors(&bl_).unwrap_or(vec![]);
    if bl_preds.len() > 0 {
      let bl_pred = g.node(bl_preds.first().unwrap()).unwrap();
      let br_pred = g.node(g.predecessors(&br_).unwrap_or(vec![]).first().unwrap()).unwrap();
      // not required as it was handled by structs' default
      /*
      if (!_.has(result, "barycenter")) {
        result.barycenter = 0;
        result.weight = 0;
      }
      */
      let bl_pred_order = bl_pred.order.clone().unwrap_or(0) as f32;
      let br_pred_order = br_pred.order.clone().unwrap_or(0) as f32;
      result.barycenter =
        ( result.barycenter * result.weight + bl_pred_order + br_pred_order ) / (result.weight + 2.0);
      result.weight += 2.0;
    }
  }

  return result;
}

fn expand_subgraphs(entries: &mut Vec<ResolvedBaryEntry>, subgraphs: &OrderedHashMap<String, SubgraphResult>) {
  entries.iter_mut().for_each(|entry| {
    let mut vs: Vec<String> = vec![];
    entry.vs.iter().for_each(|v| {
      if subgraphs.contains_key(v) {
        let subgraph = subgraphs.get(v).unwrap();
        subgraph.vs.iter().for_each(|v_| {
          vs.push(v_.clone());
        });
        return ();
      }
      vs.push(v.clone());
    });

    entry.vs = vs;
  });
}

fn merge_barycenters(target: &mut Barycenter, other: &SubgraphResult) {
  let target_barycenter = target.barycenter.clone().unwrap_or(0.0);
  if target.barycenter.is_some() && target_barycenter > 0.0 {
    let target_weight = target.weight.clone().unwrap_or(0.0);

    target.barycenter = Some(
      (target_barycenter * target_weight + other.barycenter * other.weight)
        / (target_weight + other.weight)
    );
    target.weight = Some(target_weight + other.weight.clone());
  } else {
    target.barycenter = Some(other.barycenter.clone());
    target.weight = Some(other.weight.clone());
  }
}