use crate::traits::{Directed, GraphIter, GraphIterator, Undirected};
use std::marker::PhantomData;
pub trait Adjacencies<'a> {
type Node: Copy + Eq + 'a;
type Edge: Copy + Eq + 'a;
type IncidenceIt: GraphIterator<Self, Item = (Self::Edge, Self::Node)>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt;
fn neighs<'b>(&'b self, u: Self::Node) -> GraphIter<'b, Self, Self::IncidenceIt>
where
'a: 'b,
Self: Sized,
{
GraphIter(self.neigh_iter(u), self)
}
fn filter<P>(self, predicate: P) -> FilterAdjacencies<Self, P>
where
Self: Sized,
P: for<'r> Fn(&'r (Self::Edge, Self::Node)) -> bool,
{
FilterAdjacencies(self, predicate)
}
}
pub struct FilterAdjacencies<A, P>(A, P);
#[derive(Clone)]
pub struct Filtered<I>(I);
impl<A, P, I> GraphIterator<FilterAdjacencies<A, P>> for Filtered<I>
where
I: GraphIterator<A>,
P: for<'r> Fn(&'r I::Item) -> bool,
{
type Item = I::Item;
fn next(&mut self, adj: &FilterAdjacencies<A, P>) -> Option<Self::Item> {
while let Some(it) = self.0.next(&adj.0) {
if (adj.1)(&it) {
return Some(it);
}
}
None
}
}
impl<'a, A, P> Adjacencies<'a> for FilterAdjacencies<A, P>
where
A: Adjacencies<'a>,
P: 'a + Clone + for<'r> Fn(&'r (A::Edge, A::Node)) -> bool,
{
type Node = A::Node;
type Edge = A::Edge;
type IncidenceIt = Filtered<A::IncidenceIt>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
Filtered(self.0.neigh_iter(u))
}
}
#[derive(Clone)]
pub struct AdjacenciesWrapIt<I>(I);
impl<I> From<I> for AdjacenciesWrapIt<I> {
fn from(it: I) -> Self {
AdjacenciesWrapIt(it)
}
}
impl<'g, G, I> GraphIterator<Neighbors<'g, G>> for AdjacenciesWrapIt<I>
where
I: GraphIterator<G>,
{
type Item = I::Item;
fn next(&mut self, adj: &Neighbors<'g, G>) -> Option<Self::Item> {
self.0.next(adj.0)
}
fn size_hint(&self, adj: &Neighbors<'g, G>) -> (usize, Option<usize>) {
self.0.size_hint(adj.0)
}
fn count(self, adj: &Neighbors<'g, G>) -> usize {
self.0.count(adj.0)
}
}
impl<'g, G, I> GraphIterator<OutEdges<'g, G>> for AdjacenciesWrapIt<I>
where
I: GraphIterator<G>,
{
type Item = I::Item;
fn next(&mut self, adj: &OutEdges<'g, G>) -> Option<Self::Item> {
self.0.next(adj.0)
}
fn size_hint(&self, adj: &OutEdges<'g, G>) -> (usize, Option<usize>) {
self.0.size_hint(adj.0)
}
fn count(self, adj: &OutEdges<'g, G>) -> usize {
self.0.count(adj.0)
}
}
impl<'g, G, I> GraphIterator<InEdges<'g, G>> for AdjacenciesWrapIt<I>
where
I: GraphIterator<G>,
{
type Item = I::Item;
fn next(&mut self, adj: &InEdges<'g, G>) -> Option<Self::Item> {
self.0.next(adj.0)
}
fn size_hint(&self, adj: &InEdges<'g, G>) -> (usize, Option<usize>) {
self.0.size_hint(adj.0)
}
fn count(self, adj: &InEdges<'g, G>) -> usize {
self.0.count(adj.0)
}
}
pub struct Neighbors<'g, G>(pub &'g G);
impl<'a, 'g: 'a, G> Adjacencies<'a> for Neighbors<'g, G>
where
G: Undirected,
{
type Node = G::Node<'a>;
type Edge = G::Edge<'a>;
type IncidenceIt = AdjacenciesWrapIt<G::NeighIt<'a>>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
self.0.neigh_iter(u).into()
}
}
pub struct OutEdges<'g, G>(pub &'g G);
impl<'a, 'g: 'a, G> Adjacencies<'a> for OutEdges<'g, G>
where
G: Directed,
{
type Node = G::Node<'a>;
type Edge = G::Edge<'a>;
type IncidenceIt = AdjacenciesWrapIt<G::OutIt<'a>>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
self.0.out_iter(u).into()
}
}
pub struct InEdges<'g, G>(pub &'g G);
impl<'a, 'g: 'a, G> Adjacencies<'a> for InEdges<'g, G>
where
G: Directed,
{
type Node = G::Node<'a>;
type Edge = G::Edge<'a>;
type IncidenceIt = AdjacenciesWrapIt<G::InIt<'a>>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
self.0.in_iter(u).into()
}
}
impl<'a, A, I> GraphIterator<&'a A> for AdjacenciesWrapIt<I>
where
I: GraphIterator<A>,
{
type Item = I::Item;
fn next(&mut self, adj: &&'a A) -> Option<Self::Item> {
self.0.next(*adj)
}
fn size_hint(&self, adj: &&'a A) -> (usize, Option<usize>) {
self.0.size_hint(*adj)
}
fn count(self, adj: &&'a A) -> usize {
self.0.count(*adj)
}
}
impl<'a, A> Adjacencies<'a> for &'a A
where
A: Adjacencies<'a>,
{
type Node = A::Node;
type Edge = A::Edge;
type IncidenceIt = AdjacenciesWrapIt<A::IncidenceIt>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
(*self).neigh_iter(u).into()
}
}
pub struct FnAdj<N, E, Ne, NeIt> {
neighsfn: Ne,
phantom: PhantomData<(N, E, NeIt)>,
}
#[derive(Clone)]
pub struct FnNeighIt<NeIt>
where
NeIt: Clone,
{
it: NeIt,
}
impl<N, E, Ne, NeIt> GraphIterator<FnAdj<N, E, Ne, NeIt>> for FnNeighIt<NeIt>
where
NeIt: Iterator<Item = (E, N)> + Clone,
{
type Item = (E, N);
fn next(&mut self, _g: &FnAdj<N, E, Ne, NeIt>) -> Option<Self::Item> {
self.it.next()
}
}
impl<'a, N, E, Ne, NeIt: Clone> Adjacencies<'a> for FnAdj<N, E, Ne, NeIt>
where
N: Copy + Eq + 'a,
E: Copy + Eq + 'a,
Ne: Fn(N) -> NeIt,
NeIt: Iterator<Item = (E, N)> + Clone,
{
type Node = N;
type Edge = E;
type IncidenceIt = FnNeighIt<NeIt>;
fn neigh_iter(&self, u: Self::Node) -> Self::IncidenceIt {
FnNeighIt { it: (self.neighsfn)(u) }
}
}
impl<'a, N, E, Ne, NeIt: Clone> From<Ne> for FnAdj<N, E, Ne, NeIt>
where
N: Copy + Eq + 'a,
E: Copy + Eq + 'a,
Ne: Fn(N) -> NeIt,
NeIt: Iterator<Item = (E, N)> + Clone,
{
fn from(neighs: Ne) -> Self {
FnAdj {
neighsfn: neighs,
phantom: PhantomData,
}
}
}