configbuilder_pattern_loader/
topology.rs1use crate::{ConfigError, TopologyOps};
2
3pub struct Topology;
5
6impl TopologyOps for Topology {
7 fn sort(&self, names: &[&str], requires: &[&[&str]]) -> Result<Vec<usize>, ConfigError> {
8 let n = names.len();
9 let index: std::collections::HashMap<&str, usize> = names
10 .iter()
11 .enumerate()
12 .map(|(i, &name)| (name, i))
13 .collect();
14
15 let mut adj: Vec<Vec<usize>> = vec![vec![]; n];
16 let mut in_degree: Vec<usize> = vec![0; n];
17
18 for (i, deps) in requires.iter().enumerate() {
19 for dep in *deps {
20 if let Some(&j) = index.get(dep) {
21 adj[j].push(i);
22 in_degree[i] += 1;
23 }
24 }
25 }
26
27 let mut queue: std::collections::VecDeque<usize> = in_degree
28 .iter()
29 .enumerate()
30 .filter(|(_, &d)| d == 0)
31 .map(|(i, _)| i)
32 .collect();
33
34 let mut order = Vec::with_capacity(n);
35 while let Some(i) = queue.pop_front() {
36 order.push(i);
37 for &j in &adj[i] {
38 in_degree[j] -= 1;
39 if in_degree[j] == 0 {
40 queue.push_back(j);
41 }
42 }
43 }
44
45 if order.len() == n {
46 Ok(order)
47 } else {
48 let cycle: Vec<&str> = names
49 .iter()
50 .enumerate()
51 .filter(|(i, _)| in_degree[*i] > 0)
52 .map(|(_, name)| *name)
53 .collect();
54 Err(ConfigError::Validation {
55 section: String::from("dependency_graph"),
56 reason: format!("dependency cycle detected among: {}", cycle.join(", ")),
57 })
58 }
59 }
60}