//! Graph traversing structs. use crate::edge::{ CompactDirection, Direction::{self, Outgoing}, EdgeType, }; use crate::node::NodeTrait; use crate::Undirected; use std::marker::PhantomData; use std::slice::Iter; pub struct Neighbors<'a, N, Ty = Undirected> where N: 'a, Ty: EdgeType, { iter: Iter<'a, (N, CompactDirection)>, ty: PhantomData, } impl<'a, N, Ty> Neighbors<'a, N, Ty> where N: 'a, Ty: EdgeType, { pub fn new(iter: Iter<'a, (N, CompactDirection)>, ty: PhantomData) -> Self { Self { iter, ty } } } impl<'a, N, Ty> Iterator for Neighbors<'a, N, Ty> where N: NodeTrait, Ty: EdgeType, { type Item = N; fn next(&mut self) -> Option { if Ty::is_directed() { (&mut self.iter) .filter_map(|&(n, dir)| if dir == Outgoing { Some(n) } else { None }) .next() } else { self.iter.next().map(|&(n, _)| n) } } } pub struct NeighborsDirected<'a, N, Ty> where N: 'a, Ty: EdgeType, { iter: Iter<'a, (N, CompactDirection)>, dir: Direction, ty: PhantomData, } impl<'a, N, Ty> NeighborsDirected<'a, N, Ty> where N: 'a, Ty: EdgeType, { pub fn new(iter: Iter<'a, (N, CompactDirection)>, dir: Direction, ty: PhantomData) -> Self { Self { iter, dir, ty } } } impl<'a, N, Ty> Iterator for NeighborsDirected<'a, N, Ty> where N: NodeTrait, Ty: EdgeType, { type Item = N; fn next(&mut self) -> Option { if Ty::is_directed() { let self_dir = self.dir; (&mut self.iter) .filter_map(move |&(n, dir)| if dir == self_dir { Some(n) } else { None }) .next() } else { self.iter.next().map(|&(n, _)| n) } } } #[cfg(test)] mod tests { use crate::edge::{ CompactDirection, Direction::{Incoming, Outgoing}, }; use crate::graph::{Directed, Undirected}; use crate::traverse::{Neighbors, NeighborsDirected}; use std::marker::PhantomData; #[test] fn neighbors_new() { let nodes: Vec<(u32, CompactDirection)> = vec![]; let iter = nodes.iter(); // Test `Neighbors` struct creation. let _n: Neighbors = Neighbors::new(iter, PhantomData); } #[test] fn neighbors_next() { let nodes: Vec<(u32, CompactDirection)> = vec![ (1, CompactDirection::Incoming), (2, CompactDirection::Outgoing), (3, CompactDirection::Outgoing), ]; let iter = nodes.iter(); let mut neighbors_directed: Neighbors = Neighbors::new(iter.clone(), PhantomData); assert_eq!(neighbors_directed.next(), Some(2)); assert_eq!(neighbors_directed.next(), Some(3)); assert_eq!(neighbors_directed.next(), None); let mut neighbors_undirected: Neighbors = Neighbors::new(iter.clone(), PhantomData); assert_eq!(neighbors_undirected.next(), Some(1)); assert_eq!(neighbors_undirected.next(), Some(2)); assert_eq!(neighbors_undirected.next(), Some(3)); assert_eq!(neighbors_undirected.next(), None); } #[test] fn neighbors_directed_new() { let nodes: Vec<(u32, CompactDirection)> = vec![]; let iter = nodes.iter(); // Test `Neighbors` struct creation. let _n: NeighborsDirected = NeighborsDirected::new(iter, Incoming, PhantomData); } #[test] fn neighbors_directed_next() { let nodes: Vec<(u32, CompactDirection)> = vec![ (1, CompactDirection::Incoming), (2, CompactDirection::Outgoing), (3, CompactDirection::Outgoing), ]; let iter = nodes.iter(); let mut neighbors_incomming: NeighborsDirected = NeighborsDirected::new(iter.clone(), Incoming, PhantomData); assert_eq!(neighbors_incomming.next(), Some(1)); assert_eq!(neighbors_incomming.next(), None); let mut neighbors_outgoing: NeighborsDirected = NeighborsDirected::new(iter.clone(), Outgoing, PhantomData); assert_eq!(neighbors_outgoing.next(), Some(2)); assert_eq!(neighbors_outgoing.next(), Some(3)); assert_eq!(neighbors_outgoing.next(), None); let mut neighbors_undirected: NeighborsDirected = NeighborsDirected::new(iter, Outgoing, PhantomData); assert_eq!(neighbors_undirected.next(), Some(1)); assert_eq!(neighbors_undirected.next(), Some(2)); assert_eq!(neighbors_undirected.next(), Some(3)); assert_eq!(neighbors_undirected.next(), None); } }