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
}