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