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