use self::Direction::{Incoming, Outgoing};
use crate::graph::{Directed, Graph, Undirected};
use crate::node::NodeTrait;
use crate::traverse::Neighbors;
use indexmap::map::Iter as IndexMapIter;
use indexmap::IndexMap;
use std::marker::PhantomData;
pub trait EdgeType {
fn is_directed() -> bool;
}
impl EdgeType for Directed {
#[inline]
fn is_directed() -> bool {
true
}
}
impl EdgeType for Undirected {
#[inline]
fn is_directed() -> bool {
false
}
}
pub struct Edges<'a, N, E: 'a, Ty>
where
N: 'a + NodeTrait,
Ty: EdgeType,
{
from: N,
edges: &'a IndexMap<(N, N), E>,
iter: Neighbors<'a, N, Ty>,
}
impl<'a, N, E, Ty> Edges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
Ty: EdgeType,
{
pub fn new(from: N, edges: &'a IndexMap<(N, N), E>, iter: Neighbors<'a, N, Ty>) -> Self {
Self { from, edges, iter }
}
}
impl<'a, N, E, Ty> Iterator for Edges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = (N, N, &'a E);
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
None => None,
Some(b) => {
let a = self.from;
match self.edges.get(&Graph::<N, E, Ty>::edge_key(a, b)) {
None => unreachable!(),
Some(edge) => Some((a, b, edge)),
}
}
}
}
}
pub struct AllEdges<'a, N, E: 'a, Ty> {
inner: IndexMapIter<'a, (N, N), E>,
ty: PhantomData<Ty>,
}
impl<'a, N, E, Ty> AllEdges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
{
pub fn new(inner: IndexMapIter<'a, (N, N), E>, ty: PhantomData<Ty>) -> Self {
Self { inner, ty }
}
}
impl<'a, N, E, Ty> Iterator for AllEdges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
type Item = (N, N, &'a E);
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
None => None,
Some((&(a, b), v)) => Some((a, b, v)),
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
fn count(self) -> usize {
self.inner.count()
}
fn nth(&mut self, n: usize) -> Option<Self::Item> {
self.inner
.nth(n)
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
fn last(self) -> Option<Self::Item> {
self.inner
.last()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
}
impl<'a, N, E, Ty> DoubleEndedIterator for AllEdges<'a, N, E, Ty>
where
N: 'a + NodeTrait,
E: 'a,
Ty: EdgeType,
{
fn next_back(&mut self) -> Option<Self::Item> {
self.inner
.next_back()
.map(|(&(n1, n2), weight)| (n1, n2, weight))
}
}
pub trait IntoWeightedEdge<E> {
type NodeId;
fn into_weighted_edge(self) -> (Self::NodeId, Self::NodeId, E);
}
impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix)
where
E: Default,
{
type NodeId = Ix;
fn into_weighted_edge(self) -> (Ix, Ix, E) {
let (s, t) = self;
(s, t, E::default())
}
}
impl<Ix, E> IntoWeightedEdge<E> for (Ix, Ix, E) {
type NodeId = Ix;
fn into_weighted_edge(self) -> (Ix, Ix, E) {
self
}
}
impl<'a, Ix, E> IntoWeightedEdge<E> for (Ix, Ix, &'a E)
where
E: Clone,
{
type NodeId = Ix;
fn into_weighted_edge(self) -> (Ix, Ix, E) {
let (a, b, c) = self;
(a, b, c.clone())
}
}
impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix)
where
Ix: Copy,
E: Default,
{
type NodeId = Ix;
fn into_weighted_edge(self) -> (Ix, Ix, E) {
let (s, t) = *self;
(s, t, E::default())
}
}
impl<'a, Ix, E> IntoWeightedEdge<E> for &'a (Ix, Ix, E)
where
Ix: Copy,
E: Clone,
{
type NodeId = Ix;
fn into_weighted_edge(self) -> (Ix, Ix, E) {
self.clone()
}
}
#[derive(Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)]
#[repr(usize)]
pub enum Direction {
Outgoing = 0,
Incoming = 1,
}
copyclone!(Direction);
impl Direction {
#[inline]
pub fn opposite(self) -> Direction {
match self {
Outgoing => Incoming,
Incoming => Outgoing,
}
}
#[inline]
pub fn index(self) -> usize {
(self as usize) & 0x1
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum CompactDirection {
Outgoing,
Incoming,
}
impl From<Direction> for CompactDirection {
fn from(d: Direction) -> Self {
match d {
Outgoing => CompactDirection::Outgoing,
Incoming => CompactDirection::Incoming,
}
}
}
impl PartialEq<Direction> for CompactDirection {
fn eq(&self, rhs: &Direction) -> bool {
(*self as usize) == (*rhs as usize)
}
}