1use crate::traits::{Directed, GraphIter, GraphIterator, Undirected};
59use std::marker::PhantomData;
60
61pub trait Adjacencies<'a> {
64    type Node: Copy + Eq + 'a;
65
66    type Edge: Copy + Eq + 'a;
67
68    type IncidenceIt: GraphIterator<Self, Item = (Self::Edge, Self::Node)>;
69
70    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt;
71
72    fn neighs<'b>(&'b self, u: Self::Node) -> GraphIter<'b, Self, Self::IncidenceIt>
73    where
74        'a: 'b,
75        Self: Sized,
76    {
77        GraphIter(self.neigh_iter(u), self)
78    }
79
80    fn filter<P>(self, predicate: P) -> FilterAdjacencies<Self, P>
81    where
82        Self: Sized,
83        P: for<'r> Fn(&'r (Self::Edge, Self::Node)) -> bool,
84    {
85        FilterAdjacencies(self, predicate)
86    }
87}
88
89pub struct FilterAdjacencies<A, P>(A, P);
90
91#[derive(Clone)]
92pub struct Filtered<I>(I);
93
94impl<A, P, I> GraphIterator<FilterAdjacencies<A, P>> for Filtered<I>
95where
96    I: GraphIterator<A>,
97    P: for<'r> Fn(&'r I::Item) -> bool,
98{
99    type Item = I::Item;
100
101    fn next(&mut self, adj: &FilterAdjacencies<A, P>) -> Option<Self::Item> {
102        while let Some(it) = self.0.next(&adj.0) {
103            if (adj.1)(&it) {
104                return Some(it);
105            }
106        }
107        None
108    }
109}
110
111impl<'a, A, P> Adjacencies<'a> for FilterAdjacencies<A, P>
112where
113    A: Adjacencies<'a>,
114    P: 'a + Clone + for<'r> Fn(&'r (A::Edge, A::Node)) -> bool,
115{
116    type Node = A::Node;
117    type Edge = A::Edge;
118    type IncidenceIt = Filtered<A::IncidenceIt>;
119
120    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
121        Filtered(self.0.neigh_iter(u))
122    }
123}
124
125#[derive(Clone)]
126pub struct AdjacenciesWrapIt<I>(I);
127
128impl<I> From<I> for AdjacenciesWrapIt<I> {
129    fn from(it: I) -> Self {
130        AdjacenciesWrapIt(it)
131    }
132}
133
134impl<'g, G, I> GraphIterator<Neighbors<'g, G>> for AdjacenciesWrapIt<I>
135where
136    I: GraphIterator<G>,
137{
138    type Item = I::Item;
139
140    fn next(&mut self, adj: &Neighbors<'g, G>) -> Option<Self::Item> {
141        self.0.next(adj.0)
142    }
143
144    fn size_hint(&self, adj: &Neighbors<'g, G>) -> (usize, Option<usize>) {
145        self.0.size_hint(adj.0)
146    }
147
148    fn count(self, adj: &Neighbors<'g, G>) -> usize {
149        self.0.count(adj.0)
150    }
151}
152
153impl<'g, G, I> GraphIterator<OutEdges<'g, G>> for AdjacenciesWrapIt<I>
154where
155    I: GraphIterator<G>,
156{
157    type Item = I::Item;
158
159    fn next(&mut self, adj: &OutEdges<'g, G>) -> Option<Self::Item> {
160        self.0.next(adj.0)
161    }
162
163    fn size_hint(&self, adj: &OutEdges<'g, G>) -> (usize, Option<usize>) {
164        self.0.size_hint(adj.0)
165    }
166
167    fn count(self, adj: &OutEdges<'g, G>) -> usize {
168        self.0.count(adj.0)
169    }
170}
171
172impl<'g, G, I> GraphIterator<InEdges<'g, G>> for AdjacenciesWrapIt<I>
173where
174    I: GraphIterator<G>,
175{
176    type Item = I::Item;
177
178    fn next(&mut self, adj: &InEdges<'g, G>) -> Option<Self::Item> {
179        self.0.next(adj.0)
180    }
181
182    fn size_hint(&self, adj: &InEdges<'g, G>) -> (usize, Option<usize>) {
183        self.0.size_hint(adj.0)
184    }
185
186    fn count(self, adj: &InEdges<'g, G>) -> usize {
187        self.0.count(adj.0)
188    }
189}
190
191pub struct Neighbors<'g, G>(pub &'g G);
193
194impl<'a, 'g: 'a, G> Adjacencies<'a> for Neighbors<'g, G>
195where
196    G: Undirected,
197{
198    type Node = G::Node<'a>;
199    type Edge = G::Edge<'a>;
200    type IncidenceIt = AdjacenciesWrapIt<G::NeighIt<'a>>;
201
202    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
203        self.0.neigh_iter(u).into()
204    }
205}
206
207pub struct OutEdges<'g, G>(pub &'g G);
209
210impl<'a, 'g: 'a, G> Adjacencies<'a> for OutEdges<'g, G>
211where
212    G: Directed,
213{
214    type Node = G::Node<'a>;
215    type Edge = G::Edge<'a>;
216    type IncidenceIt = AdjacenciesWrapIt<G::OutIt<'a>>;
217
218    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
219        self.0.out_iter(u).into()
220    }
221}
222
223pub struct InEdges<'g, G>(pub &'g G);
225
226impl<'a, 'g: 'a, G> Adjacencies<'a> for InEdges<'g, G>
227where
228    G: Directed,
229{
230    type Node = G::Node<'a>;
231    type Edge = G::Edge<'a>;
232    type IncidenceIt = AdjacenciesWrapIt<G::InIt<'a>>;
233
234    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
235        self.0.in_iter(u).into()
236    }
237}
238
239impl<'a, A, I> GraphIterator<&'a A> for AdjacenciesWrapIt<I>
240where
241    I: GraphIterator<A>,
242{
243    type Item = I::Item;
244
245    fn next(&mut self, adj: &&'a A) -> Option<Self::Item> {
246        self.0.next(*adj)
247    }
248
249    fn size_hint(&self, adj: &&'a A) -> (usize, Option<usize>) {
250        self.0.size_hint(*adj)
251    }
252
253    fn count(self, adj: &&'a A) -> usize {
254        self.0.count(*adj)
255    }
256}
257
258impl<'a, A> Adjacencies<'a> for &'a A
260where
261    A: Adjacencies<'a>,
262{
263    type Node = A::Node;
264    type Edge = A::Edge;
265    type IncidenceIt = AdjacenciesWrapIt<A::IncidenceIt>;
266
267    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
268        (*self).neigh_iter(u).into()
269    }
270}
271
272pub struct FnAdj<N, E, Ne, NeIt> {
315    neighsfn: Ne,
316    phantom: PhantomData<(N, E, NeIt)>,
317}
318
319#[derive(Clone)]
320pub struct FnNeighIt<NeIt>
321where
322    NeIt: Clone,
323{
324    it: NeIt,
325}
326
327impl<N, E, Ne, NeIt> GraphIterator<FnAdj<N, E, Ne, NeIt>> for FnNeighIt<NeIt>
328where
329    NeIt: Iterator<Item = (E, N)> + Clone,
330{
331    type Item = (E, N);
332    fn next(&mut self, _g: &FnAdj<N, E, Ne, NeIt>) -> Option<Self::Item> {
333        self.it.next()
334    }
335}
336
337impl<'a, N, E, Ne, NeIt: Clone> Adjacencies<'a> for FnAdj<N, E, Ne, NeIt>
338where
339    N: Copy + Eq + 'a,
340    E: Copy + Eq + 'a,
341    Ne: Fn(N) -> NeIt,
342    NeIt: Iterator<Item = (E, N)> + Clone,
343{
344    type Node = N;
345    type Edge = E;
346    type IncidenceIt = FnNeighIt<NeIt>;
347
348    fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
349        FnNeighIt { it: (self.neighsfn)(u) }
350    }
351}
352
353impl<'a, N, E, Ne, NeIt: Clone> From<Ne> for FnAdj<N, E, Ne, NeIt>
354where
355    N: Copy + Eq + 'a,
356    E: Copy + Eq + 'a,
357    Ne: Fn(N) -> NeIt,
358    NeIt: Iterator<Item = (E, N)> + Clone,
359{
360    fn from(neighs: Ne) -> Self {
361        FnAdj {
362            neighsfn: neighs,
363            phantom: PhantomData,
364        }
365    }
366}