stack_graphs/serde/
filter.rs1use itertools::Itertools;
9
10use crate::arena::Handle;
11use crate::graph::File;
12use crate::graph::Node;
13use crate::graph::StackGraph;
14use crate::partial::PartialPath;
15use crate::partial::PartialPaths;
16
17pub trait Filter {
18 fn include_file(&self, graph: &StackGraph, file: &Handle<File>) -> bool;
20
21 fn include_node(&self, graph: &StackGraph, node: &Handle<Node>) -> bool;
24
25 fn include_edge(&self, graph: &StackGraph, source: &Handle<Node>, sink: &Handle<Node>) -> bool;
28
29 fn include_partial_path(
32 &self,
33 graph: &StackGraph,
34 paths: &PartialPaths,
35 path: &PartialPath,
36 ) -> bool;
37}
38
39impl<F> Filter for F
40where
41 F: Fn(&StackGraph, &Handle<File>) -> bool,
42{
43 fn include_file(&self, graph: &StackGraph, file: &Handle<File>) -> bool {
44 self(graph, file)
45 }
46
47 fn include_node(&self, _graph: &StackGraph, _node: &Handle<Node>) -> bool {
48 true
49 }
50
51 fn include_edge(
52 &self,
53 _graph: &StackGraph,
54 _source: &Handle<Node>,
55 _sink: &Handle<Node>,
56 ) -> bool {
57 true
58 }
59
60 fn include_partial_path(
61 &self,
62 _graph: &StackGraph,
63 _paths: &PartialPaths,
64 _path: &PartialPath,
65 ) -> bool {
66 true
67 }
68}
69
70pub struct NoFilter;
72
73impl Filter for NoFilter {
74 fn include_file(&self, _graph: &StackGraph, _file: &Handle<File>) -> bool {
75 true
76 }
77
78 fn include_node(&self, _graph: &StackGraph, _node: &Handle<Node>) -> bool {
79 true
80 }
81
82 fn include_edge(
83 &self,
84 _graph: &StackGraph,
85 _source: &Handle<Node>,
86 _sink: &Handle<Node>,
87 ) -> bool {
88 true
89 }
90
91 fn include_partial_path(
92 &self,
93 _graph: &StackGraph,
94 _paths: &PartialPaths,
95 _path: &PartialPath,
96 ) -> bool {
97 true
98 }
99}
100
101pub struct FileFilter(pub Handle<File>);
103
104impl Filter for FileFilter {
105 fn include_file(&self, _graph: &StackGraph, file: &Handle<File>) -> bool {
106 *file == self.0
107 }
108
109 fn include_node(&self, _graph: &StackGraph, _node: &Handle<Node>) -> bool {
110 true
111 }
112
113 fn include_edge(
114 &self,
115 _graph: &StackGraph,
116 _source: &Handle<Node>,
117 _sink: &Handle<Node>,
118 ) -> bool {
119 true
120 }
121
122 fn include_partial_path(
123 &self,
124 _graph: &StackGraph,
125 _paths: &PartialPaths,
126 _path: &PartialPath,
127 ) -> bool {
128 true
129 }
130}
131
132pub(crate) struct ImplicationFilter<'a>(pub &'a dyn Filter);
135
136impl Filter for ImplicationFilter<'_> {
137 fn include_file(&self, graph: &StackGraph, file: &Handle<File>) -> bool {
138 self.0.include_file(graph, file)
139 }
140
141 fn include_node(&self, graph: &StackGraph, node: &Handle<Node>) -> bool {
142 graph[*node]
143 .id()
144 .file()
145 .map_or(true, |f| self.include_file(graph, &f))
146 && self.0.include_node(graph, node)
147 }
148
149 fn include_edge(&self, graph: &StackGraph, source: &Handle<Node>, sink: &Handle<Node>) -> bool {
150 self.include_node(graph, source)
151 && self.include_node(graph, sink)
152 && self.0.include_edge(graph, source, sink)
153 }
154
155 fn include_partial_path(
156 &self,
157 graph: &StackGraph,
158 paths: &PartialPaths,
159 path: &PartialPath,
160 ) -> bool {
161 let super_ok = self.0.include_partial_path(graph, paths, path);
162 if !super_ok {
163 return false;
164 }
165 let all_included_edges = path
166 .edges
167 .iter_unordered(paths)
168 .map(|e| graph.node_for_id(e.source_node_id).unwrap())
169 .chain(std::iter::once(path.end_node))
170 .tuple_windows()
171 .all(|(source, sink)| self.include_edge(graph, &source, &sink));
172 if !all_included_edges {
173 return false;
174 }
175 true
176 }
177}