1 | use super::*; |
2 | |
3 | #[derive (Clone, Debug, PartialEq, Eq)] |
4 | pub struct TypeMap(HashMap<TypeName, HashSet<Type>>); |
5 | |
6 | impl std::ops::Deref for TypeMap { |
7 | type Target = HashMap<TypeName, HashSet<Type>>; |
8 | |
9 | fn deref(&self) -> &Self::Target { |
10 | &self.0 |
11 | } |
12 | } |
13 | |
14 | impl TypeMap { |
15 | pub fn new() -> Self { |
16 | Self(HashMap::new()) |
17 | } |
18 | |
19 | pub fn filter(reader: &'static Reader, filter: &Filter, references: &References) -> Self { |
20 | let mut dependencies = Self::new(); |
21 | |
22 | for namespace in reader.keys() { |
23 | if filter.includes_namespace(namespace) { |
24 | for (name, types) in &reader[namespace] { |
25 | if filter.includes_type_name(TypeName(namespace, name)) { |
26 | let mut item_dependencies = Self::new(); |
27 | |
28 | for ty in types { |
29 | ty.dependencies(&mut item_dependencies); |
30 | } |
31 | |
32 | if item_dependencies.excluded(filter) { |
33 | continue; |
34 | } |
35 | |
36 | for ty in types { |
37 | dependencies.insert(ty.clone()); |
38 | } |
39 | |
40 | dependencies.combine_references(&item_dependencies, references); |
41 | } |
42 | } |
43 | } |
44 | } |
45 | |
46 | dependencies |
47 | } |
48 | |
49 | pub fn insert(&mut self, ty: Type) -> bool { |
50 | self.0.entry(ty.type_name()).or_default().insert(ty) |
51 | } |
52 | |
53 | fn combine_references(&mut self, other: &Self, references: &References) { |
54 | for (tn, types) in &other.0 { |
55 | if references.contains(*tn).is_none() { |
56 | let set = self.0.entry(*tn).or_default(); |
57 | types.iter().for_each(|ty| { |
58 | set.insert(ty.clone()); |
59 | }); |
60 | } |
61 | } |
62 | } |
63 | |
64 | pub fn combine(&mut self, other: &Self) { |
65 | for (name, types) in &other.0 { |
66 | let set = self.0.entry(*name).or_default(); |
67 | types.iter().for_each(|ty| { |
68 | set.insert(ty.clone()); |
69 | }); |
70 | } |
71 | } |
72 | |
73 | pub fn difference(&self, other: &Self) -> Self { |
74 | Self( |
75 | self.0 |
76 | .iter() |
77 | .filter(|(tn, _)| !other.0.contains_key(tn)) |
78 | .map(|(tn, ty)| (*tn, ty.clone())) |
79 | .collect(), |
80 | ) |
81 | } |
82 | |
83 | pub fn included(&self, config: &Config) -> bool { |
84 | self.0.iter().all(|(tn, _)| { |
85 | // An empty namespace covers core types like `HRESULT`. This way we don't exclude methods |
86 | // that depend on core types that aren't explicitly included in the filter. |
87 | if tn.namespace().is_empty() { |
88 | return true; |
89 | } |
90 | |
91 | if config.types.contains_key(tn) { |
92 | return true; |
93 | } |
94 | |
95 | if config.references.contains(*tn).is_some() { |
96 | return true; |
97 | } |
98 | |
99 | false |
100 | }) |
101 | } |
102 | |
103 | fn excluded(&self, filter: &Filter) -> bool { |
104 | self.0.iter().any(|(tn, _)| filter.excludes_type_name(*tn)) |
105 | } |
106 | } |
107 | |