1use petgraph::algo;
2use petgraph::graphmap::DiGraphMap;
3use crate::Component;
4
5pub fn add_component(g: &mut DiGraphMap<&str, String>, c: &Component) {
16 let comp_vert = g.add_node(c.name);
17 for dep in c.dependencies.iter() {
18 let dep_vert = g.add_node(dep);
19 g.add_edge(comp_vert, dep_vert, format!("{} -> {}", c.name, dep));
20 }
21}
22
23pub fn add_components(g: &mut DiGraphMap<&str, String>, cs: Vec<Component>) {
24 for c in cs.iter() {
25 add_component(g, c);
26 }
27}
28
29pub fn sort<'a>(g: &DiGraphMap<&'a str, String>) -> Vec<&'a str> {
30 match algo::toposort(g, Option::None) {
31 Ok(sorted) => {
32 sorted
33 .iter()
34 .rev()
35 .map(| item: &&str | *item)
36 .collect()
37 },
38 Err(e) => panic!("Cyclic dependency detected for {}", e.node_id()),
39 }
40}
41
42#[cfg(test)]
47mod tests {
48 use petgraph::Directed;
49 use petgraph::graphmap::GraphMap;
50 use super::*;
51
52 #[test]
53 fn new_test() {
54 let mut g = GraphMap::<&str, String, Directed>::new();
55 let deps = vec![
56 Component{
57 name: "myapp::components::comp1",
58 dependencies: vec![
59 "myapp::components::comp2",
60 "myapp::components::comp3",
61 "myapp::components::comp4",
62 ]
63 },
64 Component {
65 name: "myapp::components::comp4",
66 dependencies: vec!["myapp::components::comp5"],
67 },
68 Component {
69 name: "myapp::components::comp5",
70 dependencies: vec!["myapp::components::comp6"],
71 },
72 Component {
73 name: "myapp::components::comp6",
74 dependencies: vec!["myapp::components::comp7"],
75 },
76 ];
77 add_components(&mut g, deps);
78 println!("{:?}", g);
79 let sorted = sort(&g);
80 assert_eq!(*sorted.last().unwrap(), "myapp::components::comp1");
81 }
82}