1use crate::prelude::*;
2
3use fixedbitset::FixedBitSet;
4use std::collections::HashSet;
5use std::marker::PhantomData;
6
7use crate::data::DataMap;
8use crate::visit::{Data, NodeCompactIndexable, NodeCount};
9use crate::visit::{
10 GraphBase, GraphProp, IntoEdgeReferences, IntoEdges, IntoEdgesDirected, IntoNeighbors,
11 IntoNeighborsDirected, IntoNodeIdentifiers, IntoNodeReferences, NodeIndexable, NodeRef,
12 VisitMap, Visitable,
13};
14
15pub trait FilterNode<N> {
17 fn include_node(&self, node: N) -> bool;
19}
20
21impl<F, N> FilterNode<N> for F
22where
23 F: Fn(N) -> bool,
24{
25 fn include_node(&self, n: N) -> bool {
26 (*self)(n)
27 }
28}
29
30impl<N> FilterNode<N> for FixedBitSet
32where
33 FixedBitSet: VisitMap<N>,
34{
35 fn include_node(&self, n: N) -> bool {
36 self.is_visited(&n)
37 }
38}
39
40impl<N, S> FilterNode<N> for HashSet<N, S>
42where
43 HashSet<N, S>: VisitMap<N>,
44{
45 fn include_node(&self, n: N) -> bool {
46 self.is_visited(&n)
47 }
48}
49
50impl<N> FilterNode<N> for &FixedBitSet
53where
54 FixedBitSet: VisitMap<N>,
55{
56 fn include_node(&self, n: N) -> bool {
57 self.is_visited(&n)
58 }
59}
60
61impl<N, S> FilterNode<N> for &HashSet<N, S>
62where
63 HashSet<N, S>: VisitMap<N>,
64{
65 fn include_node(&self, n: N) -> bool {
66 self.is_visited(&n)
67 }
68}
69
70#[derive(Copy, Clone, Debug)]
72pub struct NodeFiltered<G, F>(pub G, pub F);
73
74impl<F, G> NodeFiltered<G, F>
75where
76 G: GraphBase,
77 F: Fn(G::NodeId) -> bool,
78{
79 pub fn from_fn(graph: G, filter: F) -> Self {
81 NodeFiltered(graph, filter)
82 }
83}
84
85impl<G, F> GraphBase for NodeFiltered<G, F>
86where
87 G: GraphBase,
88{
89 type NodeId = G::NodeId;
90 type EdgeId = G::EdgeId;
91}
92
93impl<'a, G, F> IntoNeighbors for &'a NodeFiltered<G, F>
94where
95 G: IntoNeighbors,
96 F: FilterNode<G::NodeId>,
97{
98 type Neighbors = NodeFilteredNeighbors<'a, G::Neighbors, F>;
99 fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
100 NodeFilteredNeighbors {
101 include_source: self.1.include_node(n),
102 iter: self.0.neighbors(n),
103 f: &self.1,
104 }
105 }
106}
107
108pub struct NodeFilteredNeighbors<'a, I, F: 'a> {
110 include_source: bool,
111 iter: I,
112 f: &'a F,
113}
114
115impl<'a, I, F> Iterator for NodeFilteredNeighbors<'a, I, F>
116where
117 I: Iterator,
118 I::Item: Copy,
119 F: FilterNode<I::Item>,
120{
121 type Item = I::Item;
122 fn next(&mut self) -> Option<Self::Item> {
123 let f = self.f;
124 if !self.include_source {
125 None
126 } else {
127 self.iter.find(move |&target| f.include_node(target))
128 }
129 }
130}
131
132impl<'a, G, F> IntoNeighborsDirected for &'a NodeFiltered<G, F>
133where
134 G: IntoNeighborsDirected,
135 F: FilterNode<G::NodeId>,
136{
137 type NeighborsDirected = NodeFilteredNeighbors<'a, G::NeighborsDirected, F>;
138 fn neighbors_directed(self, n: G::NodeId, dir: Direction) -> Self::NeighborsDirected {
139 NodeFilteredNeighbors {
140 include_source: self.1.include_node(n),
141 iter: self.0.neighbors_directed(n, dir),
142 f: &self.1,
143 }
144 }
145}
146
147impl<'a, G, F> IntoNodeIdentifiers for &'a NodeFiltered<G, F>
148where
149 G: IntoNodeIdentifiers,
150 F: FilterNode<G::NodeId>,
151{
152 type NodeIdentifiers = NodeFilteredNeighbors<'a, G::NodeIdentifiers, F>;
153 fn node_identifiers(self) -> Self::NodeIdentifiers {
154 NodeFilteredNeighbors {
155 include_source: true,
156 iter: self.0.node_identifiers(),
157 f: &self.1,
158 }
159 }
160}
161
162impl<'a, G, F> IntoNodeReferences for &'a NodeFiltered<G, F>
163where
164 G: IntoNodeReferences,
165 F: FilterNode<G::NodeId>,
166{
167 type NodeRef = G::NodeRef;
168 type NodeReferences = NodeFilteredNodes<'a, G::NodeReferences, F>;
169 fn node_references(self) -> Self::NodeReferences {
170 NodeFilteredNodes {
171 include_source: true,
172 iter: self.0.node_references(),
173 f: &self.1,
174 }
175 }
176}
177
178pub struct NodeFilteredNodes<'a, I, F: 'a> {
180 include_source: bool,
181 iter: I,
182 f: &'a F,
183}
184
185impl<'a, I, F> Iterator for NodeFilteredNodes<'a, I, F>
186where
187 I: Iterator,
188 I::Item: Copy + NodeRef,
189 F: FilterNode<<I::Item as NodeRef>::NodeId>,
190{
191 type Item = I::Item;
192 fn next(&mut self) -> Option<Self::Item> {
193 let f = self.f;
194 if !self.include_source {
195 None
196 } else {
197 self.iter.find(move |&target| f.include_node(target.id()))
198 }
199 }
200}
201
202impl<'a, G, F> IntoEdgeReferences for &'a NodeFiltered<G, F>
203where
204 G: IntoEdgeReferences,
205 F: FilterNode<G::NodeId>,
206{
207 type EdgeRef = G::EdgeRef;
208 type EdgeReferences = NodeFilteredEdgeReferences<'a, G, G::EdgeReferences, F>;
209 fn edge_references(self) -> Self::EdgeReferences {
210 NodeFilteredEdgeReferences {
211 graph: PhantomData,
212 iter: self.0.edge_references(),
213 f: &self.1,
214 }
215 }
216}
217
218pub struct NodeFilteredEdgeReferences<'a, G, I, F: 'a> {
220 graph: PhantomData<G>,
221 iter: I,
222 f: &'a F,
223}
224
225impl<'a, G, I, F> Iterator for NodeFilteredEdgeReferences<'a, G, I, F>
226where
227 F: FilterNode<G::NodeId>,
228 G: IntoEdgeReferences,
229 I: Iterator<Item = G::EdgeRef>,
230{
231 type Item = I::Item;
232 fn next(&mut self) -> Option<Self::Item> {
233 let f = self.f;
234 self.iter
235 .find(move |&edge| f.include_node(edge.source()) && f.include_node(edge.target()))
236 }
237}
238
239impl<'a, G, F> IntoEdges for &'a NodeFiltered<G, F>
240where
241 G: IntoEdges,
242 F: FilterNode<G::NodeId>,
243{
244 type Edges = NodeFilteredEdges<'a, G, G::Edges, F>;
245 fn edges(self, a: G::NodeId) -> Self::Edges {
246 NodeFilteredEdges {
247 graph: PhantomData,
248 include_source: self.1.include_node(a),
249 iter: self.0.edges(a),
250 f: &self.1,
251 }
252 }
253}
254
255pub struct NodeFilteredEdges<'a, G, I, F: 'a> {
257 graph: PhantomData<G>,
258 include_source: bool,
259 iter: I,
260 f: &'a F,
261}
262
263impl<'a, G, I, F> Iterator for NodeFilteredEdges<'a, G, I, F>
264where
265 F: FilterNode<G::NodeId>,
266 G: IntoEdges,
267 I: Iterator<Item = G::EdgeRef>,
268{
269 type Item = I::Item;
270 fn next(&mut self) -> Option<Self::Item> {
271 if !self.include_source {
272 None
273 } else {
274 let f = self.f;
275 self.iter.find(move |&edge| f.include_node(edge.target()))
276 }
277 }
278}
279
280impl<G, F> DataMap for NodeFiltered<G, F>
281where
282 G: DataMap,
283 F: FilterNode<G::NodeId>,
284{
285 fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
286 if self.1.include_node(id) {
287 self.0.node_weight(id)
288 } else {
289 None
290 }
291 }
292
293 fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
294 self.0.edge_weight(id)
295 }
296}
297
298macro_rules! access0 {
299 ($e:expr) => {
300 $e.0
301 };
302}
303
304Data! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
305NodeIndexable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
306GraphProp! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
307Visitable! {delegate_impl [[G, F], G, NodeFiltered<G, F>, access0]}
308
309pub trait FilterEdge<Edge> {
311 fn include_edge(&self, edge: Edge) -> bool;
313}
314
315impl<F, N> FilterEdge<N> for F
316where
317 F: Fn(N) -> bool,
318{
319 fn include_edge(&self, n: N) -> bool {
320 (*self)(n)
321 }
322}
323
324#[derive(Copy, Clone, Debug)]
333pub struct EdgeFiltered<G, F>(pub G, pub F);
334
335impl<F, G> EdgeFiltered<G, F>
336where
337 G: IntoEdgeReferences,
338 F: Fn(G::EdgeRef) -> bool,
339{
340 pub fn from_fn(graph: G, filter: F) -> Self {
342 EdgeFiltered(graph, filter)
343 }
344}
345
346impl<G, F> GraphBase for EdgeFiltered<G, F>
347where
348 G: GraphBase,
349{
350 type NodeId = G::NodeId;
351 type EdgeId = G::EdgeId;
352}
353
354impl<'a, G, F> IntoNeighbors for &'a EdgeFiltered<G, F>
355where
356 G: IntoEdges,
357 F: FilterEdge<G::EdgeRef>,
358{
359 type Neighbors = EdgeFilteredNeighbors<'a, G, F>;
360 fn neighbors(self, n: G::NodeId) -> Self::Neighbors {
361 EdgeFilteredNeighbors {
362 iter: self.0.edges(n),
363 f: &self.1,
364 }
365 }
366}
367
368impl<'a, G, F> IntoNeighborsDirected for &'a EdgeFiltered<G, F>
369where
370 G: IntoEdgesDirected,
371 F: FilterEdge<G::EdgeRef>,
372{
373 type NeighborsDirected = EdgeFilteredNeighborsDirected<'a, G, F>;
374 fn neighbors_directed(self, n: G::NodeId, dir: Direction) -> Self::NeighborsDirected {
375 EdgeFilteredNeighborsDirected {
376 iter: self.0.edges_directed(n, dir),
377 f: &self.1,
378 from: n,
379 }
380 }
381}
382
383pub struct EdgeFilteredNeighbors<'a, G, F: 'a>
385where
386 G: IntoEdges,
387{
388 iter: G::Edges,
389 f: &'a F,
390}
391
392impl<'a, G, F> Iterator for EdgeFilteredNeighbors<'a, G, F>
393where
394 F: FilterEdge<G::EdgeRef>,
395 G: IntoEdges,
396{
397 type Item = G::NodeId;
398 fn next(&mut self) -> Option<Self::Item> {
399 let f = self.f;
400 (&mut self.iter)
401 .filter_map(move |edge| {
402 if f.include_edge(edge) {
403 Some(edge.target())
404 } else {
405 None
406 }
407 })
408 .next()
409 }
410}
411
412impl<'a, G, F> IntoEdgeReferences for &'a EdgeFiltered<G, F>
413where
414 G: IntoEdgeReferences,
415 F: FilterEdge<G::EdgeRef>,
416{
417 type EdgeRef = G::EdgeRef;
418 type EdgeReferences = EdgeFilteredEdges<'a, G, G::EdgeReferences, F>;
419 fn edge_references(self) -> Self::EdgeReferences {
420 EdgeFilteredEdges {
421 graph: PhantomData,
422 iter: self.0.edge_references(),
423 f: &self.1,
424 }
425 }
426}
427
428impl<'a, G, F> IntoEdges for &'a EdgeFiltered<G, F>
429where
430 G: IntoEdges,
431 F: FilterEdge<G::EdgeRef>,
432{
433 type Edges = EdgeFilteredEdges<'a, G, G::Edges, F>;
434 fn edges(self, n: G::NodeId) -> Self::Edges {
435 EdgeFilteredEdges {
436 graph: PhantomData,
437 iter: self.0.edges(n),
438 f: &self.1,
439 }
440 }
441}
442
443pub struct EdgeFilteredEdges<'a, G, I, F: 'a> {
445 graph: PhantomData<G>,
446 iter: I,
447 f: &'a F,
448}
449
450impl<'a, G, I, F> Iterator for EdgeFilteredEdges<'a, G, I, F>
451where
452 F: FilterEdge<G::EdgeRef>,
453 G: IntoEdgeReferences,
454 I: Iterator<Item = G::EdgeRef>,
455{
456 type Item = I::Item;
457 fn next(&mut self) -> Option<Self::Item> {
458 let f = self.f;
459 self.iter.find(move |&edge| f.include_edge(edge))
460 }
461}
462
463pub struct EdgeFilteredNeighborsDirected<'a, G, F: 'a>
465where
466 G: IntoEdgesDirected,
467{
468 iter: G::EdgesDirected,
469 f: &'a F,
470 from: G::NodeId,
471}
472
473impl<'a, G, F> Iterator for EdgeFilteredNeighborsDirected<'a, G, F>
474where
475 F: FilterEdge<G::EdgeRef>,
476 G: IntoEdgesDirected,
477{
478 type Item = G::NodeId;
479 fn next(&mut self) -> Option<Self::Item> {
480 let f = self.f;
481 let from = self.from;
482 (&mut self.iter)
483 .filter_map(move |edge| {
484 if f.include_edge(edge) {
485 if edge.source() != from {
486 Some(edge.source())
487 } else {
488 Some(edge.target()) }
490 } else {
491 None
492 }
493 })
494 .next()
495 }
496}
497
498Data! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
499GraphProp! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
500IntoNodeIdentifiers! {delegate_impl [['a, G, F], G, &'a EdgeFiltered<G, F>, access0]}
501IntoNodeReferences! {delegate_impl [['a, G, F], G, &'a EdgeFiltered<G, F>, access0]}
502NodeCompactIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
503NodeCount! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
504NodeIndexable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}
505Visitable! {delegate_impl [[G, F], G, EdgeFiltered<G, F>, access0]}