1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
use super::*;
use crate::SquareGraph;
use petgraph::{
    graph::IndexType,
    visit::{IntoNeighbors, IntoNeighborsDirected},
};
use std::iter::FusedIterator;

/// Neighbors of the node. See [`neighbors`](`IntoNeighbors::neighbors`).
#[derive(Clone, Debug)]
pub struct Neighbors<Ix: IndexType, S> {
    node: NodeIndex<Ix>,
    state: usize,
    h: usize,
    v: usize,
    s: PhantomData<S>,
}

impl<Ix, S> Iterator for Neighbors<Ix, S>
where
    Ix: IndexType,
    S: Shape,
{
    type Item = NodeIndex<Ix>;

    fn next(&mut self) -> Option<Self::Item> {
        loop {
            let n = self.node;
            let x = match self.state {
                0 if n.horizontal.index() != 0 => n.left(),
                0 if <S as Shape>::LOOP_HORIZONTAL && n.horizontal.index() == 0 => NodeIndex {
                    horizontal: Ix::new(self.h - 1),
                    vertical: n.vertical,
                },
                1 if n.horizontal.index() + 1 < self.h => n.right(),
                1 if <S as Shape>::LOOP_HORIZONTAL && n.horizontal.index() + 1 == self.h => {
                    NodeIndex {
                        horizontal: Ix::new(0),
                        vertical: n.vertical,
                    }
                }
                2 if n.vertical.index() != 0 => n.down(),
                2 if <S as Shape>::LOOP_VERTICAL && n.vertical.index() == 0 => NodeIndex {
                    horizontal: n.horizontal,
                    vertical: Ix::new(self.v - 1),
                },
                3 if n.vertical.index() + 1 < self.v => n.up(),
                3 if <S as Shape>::LOOP_VERTICAL && n.vertical.index() + 1 == self.v => NodeIndex {
                    horizontal: n.horizontal,
                    vertical: Ix::new(0),
                },
                4..=usize::MAX => return None,
                _ => {
                    self.state += 1;
                    continue;
                }
            };
            self.state += 1;
            return Some(x);
        }
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (0, Some(4 - self.state))
    }
}

impl<Ix, S> FusedIterator for Neighbors<Ix, S>
where
    Ix: IndexType,
    S: Shape,
{
}

impl<'a, N, E, Ix, S> IntoNeighbors for &'a SquareGraph<N, E, Ix, S>
where
    Ix: IndexType,
    S: Shape,
{
    type Neighbors = Neighbors<Ix, S>;

    fn neighbors(self: Self, a: Self::NodeId) -> Self::Neighbors {
        Neighbors {
            node: a,
            state: 0,
            h: self.horizontal_node_count(),
            v: self.vertical_node_count(),
            s: PhantomData,
        }
    }
}

impl<'a, N, E, Ix, S> IntoNeighborsDirected for &'a SquareGraph<N, E, Ix, S>
where
    Ix: IndexType,
    S: Shape,
{
    type NeighborsDirected = Neighbors<Ix, S>;

    fn neighbors_directed(
        self,
        n: Self::NodeId,
        _d: petgraph::Direction,
    ) -> Self::NeighborsDirected {
        Neighbors {
            node: n,
            state: 0,
            h: self.horizontal_node_count(),
            v: self.vertical_node_count(),
            s: PhantomData,
        }
    }
}