1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use serde_reflection::{ContainerFormat, Format, FormatHolder, Registry, Result};
use std::collections::{BTreeMap, BTreeSet, HashSet};
fn get_dependencies<'a>(
format: &'a ContainerFormat,
external: &BTreeSet<String>,
) -> Result<BTreeSet<&'a str>> {
let mut result = BTreeSet::new();
format.visit(&mut |format| {
if let Format::TypeName(x) = format {
if !external.contains(x) {
result.insert(x.as_str());
}
}
Ok(())
})?;
Ok(result)
}
pub fn get_dependency_map(registry: &Registry) -> Result<BTreeMap<&str, BTreeSet<&str>>> {
get_dependency_map_with_external_dependencies(registry, &BTreeSet::new())
}
pub fn get_dependency_map_with_external_dependencies<'a>(
registry: &'a Registry,
external: &BTreeSet<String>,
) -> Result<BTreeMap<&'a str, BTreeSet<&'a str>>> {
let mut children = BTreeMap::new();
for (name, format) in registry {
children.insert(name.as_str(), get_dependencies(format, external)?);
}
Ok(children)
}
pub fn best_effort_topological_sort<T>(children: &BTreeMap<T, BTreeSet<T>>) -> Vec<T>
where
T: Clone + std::cmp::Ord + std::cmp::Eq + std::hash::Hash,
{
let mut queue: Vec<_> = children.keys().rev().cloned().collect();
queue.sort_by(|node1, node2| children[node1].len().cmp(&children[node2].len()));
let mut result = Vec::new();
let mut sorted = HashSet::new();
let mut seen = HashSet::new();
while let Some(node) = queue.pop() {
if sorted.contains(&node) {
continue;
}
if seen.contains(&node) {
sorted.insert(node.clone());
result.push(node);
continue;
}
seen.insert(node.clone());
queue.push(node.clone());
for child in children[&node].iter().rev() {
if !seen.contains(child) {
queue.push(child.clone());
}
}
}
result
}