use crate::graph::IndexType;
#[cfg(feature = "graphmap")]
use crate::graphmap::{GraphMap, NodeTrait};
#[cfg(feature = "stable_graph")]
use crate::stable_graph::StableGraph;
use crate::visit::{Data, NodeCount, NodeIndexable, Reversed};
use crate::EdgeType;
use crate::Graph;
trait_template! {
pub trait DataMap : Data {
@section self
fn node_weight(self: &Self, id: Self::NodeId) -> Option<&Self::NodeWeight>;
fn edge_weight(self: &Self, id: Self::EdgeId) -> Option<&Self::EdgeWeight>;
}
}
macro_rules! access0 {
($e:expr) => {
$e.0
};
}
DataMap! {delegate_impl []}
DataMap! {delegate_impl [['a, G], G, &'a mut G, deref_twice]}
DataMap! {delegate_impl [[G], G, Reversed<G>, access0]}
trait_template! {
pub trait DataMapMut : DataMap {
@section self
fn node_weight_mut(self: &mut Self, id: Self::NodeId) -> Option<&mut Self::NodeWeight>;
fn edge_weight_mut(self: &mut Self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight>;
}
}
DataMapMut! {delegate_impl [['a, G], G, &'a mut G, deref_twice]}
DataMapMut! {delegate_impl [[G], G, Reversed<G>, access0]}
pub trait Build: Data + NodeCount {
fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId;
fn add_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Option<Self::EdgeId> {
Some(self.update_edge(a, b, weight))
}
fn update_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Self::EdgeId;
}
pub trait Create: Build + Default {
fn with_capacity(nodes: usize, edges: usize) -> Self;
}
impl<N, E, Ty, Ix> Data for Graph<N, E, Ty, Ix>
where
Ix: IndexType,
{
type NodeWeight = N;
type EdgeWeight = E;
}
impl<N, E, Ty, Ix> DataMap for Graph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
self.node_weight(id)
}
fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
self.edge_weight(id)
}
}
impl<N, E, Ty, Ix> DataMapMut for Graph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
self.node_weight_mut(id)
}
fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
self.edge_weight_mut(id)
}
}
#[cfg(feature = "stable_graph")]
impl<N, E, Ty, Ix> DataMap for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn node_weight(&self, id: Self::NodeId) -> Option<&Self::NodeWeight> {
self.node_weight(id)
}
fn edge_weight(&self, id: Self::EdgeId) -> Option<&Self::EdgeWeight> {
self.edge_weight(id)
}
}
#[cfg(feature = "stable_graph")]
impl<N, E, Ty, Ix> DataMapMut for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn node_weight_mut(&mut self, id: Self::NodeId) -> Option<&mut Self::NodeWeight> {
self.node_weight_mut(id)
}
fn edge_weight_mut(&mut self, id: Self::EdgeId) -> Option<&mut Self::EdgeWeight> {
self.edge_weight_mut(id)
}
}
impl<N, E, Ty, Ix> Build for Graph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
self.add_node(weight)
}
fn add_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Option<Self::EdgeId> {
Some(self.add_edge(a, b, weight))
}
fn update_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Self::EdgeId {
self.update_edge(a, b, weight)
}
}
#[cfg(feature = "stable_graph")]
impl<N, E, Ty, Ix> Build for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
self.add_node(weight)
}
fn add_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Option<Self::EdgeId> {
Some(self.add_edge(a, b, weight))
}
fn update_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Self::EdgeId {
self.update_edge(a, b, weight)
}
}
#[cfg(feature = "graphmap")]
impl<N, E, Ty> Build for GraphMap<N, E, Ty>
where
Ty: EdgeType,
N: NodeTrait,
{
fn add_node(&mut self, weight: Self::NodeWeight) -> Self::NodeId {
self.add_node(weight)
}
fn add_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Option<Self::EdgeId> {
if self.contains_edge(a, b) {
None
} else {
let r = self.add_edge(a, b, weight);
debug_assert!(r.is_none());
Some((a, b))
}
}
fn update_edge(
&mut self,
a: Self::NodeId,
b: Self::NodeId,
weight: Self::EdgeWeight,
) -> Self::EdgeId {
self.add_edge(a, b, weight);
(a, b)
}
}
impl<N, E, Ty, Ix> Create for Graph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn with_capacity(nodes: usize, edges: usize) -> Self {
Self::with_capacity(nodes, edges)
}
}
#[cfg(feature = "stable_graph")]
impl<N, E, Ty, Ix> Create for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn with_capacity(nodes: usize, edges: usize) -> Self {
Self::with_capacity(nodes, edges)
}
}
#[cfg(feature = "graphmap")]
impl<N, E, Ty> Create for GraphMap<N, E, Ty>
where
Ty: EdgeType,
N: NodeTrait,
{
fn with_capacity(nodes: usize, edges: usize) -> Self {
Self::with_capacity(nodes, edges)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Element<N, E> {
Node { weight: N },
Edge {
source: usize,
target: usize,
weight: E,
},
}
pub trait FromElements: Create {
fn from_elements<I>(iterable: I) -> Self
where
Self: Sized,
I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
{
let mut gr = Self::with_capacity(0, 0);
let mut map = Vec::new();
for element in iterable {
match element {
Element::Node { weight } => {
map.push(gr.add_node(weight));
}
Element::Edge {
source,
target,
weight,
} => {
gr.add_edge(map[source], map[target], weight);
}
}
}
gr
}
}
fn from_elements_indexable<G, I>(iterable: I) -> G
where
G: Create + NodeIndexable,
I: IntoIterator<Item = Element<G::NodeWeight, G::EdgeWeight>>,
{
let mut gr = G::with_capacity(0, 0);
let map = |gr: &G, i| gr.from_index(i);
for element in iterable {
match element {
Element::Node { weight } => {
gr.add_node(weight);
}
Element::Edge {
source,
target,
weight,
} => {
let from = map(&gr, source);
let to = map(&gr, target);
gr.add_edge(from, to, weight);
}
}
}
gr
}
impl<N, E, Ty, Ix> FromElements for Graph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn from_elements<I>(iterable: I) -> Self
where
Self: Sized,
I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
{
from_elements_indexable(iterable)
}
}
#[cfg(feature = "stable_graph")]
impl<N, E, Ty, Ix> FromElements for StableGraph<N, E, Ty, Ix>
where
Ty: EdgeType,
Ix: IndexType,
{
fn from_elements<I>(iterable: I) -> Self
where
Self: Sized,
I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
{
from_elements_indexable(iterable)
}
}
#[cfg(feature = "graphmap")]
impl<N, E, Ty> FromElements for GraphMap<N, E, Ty>
where
Ty: EdgeType,
N: NodeTrait,
{
fn from_elements<I>(iterable: I) -> Self
where
Self: Sized,
I: IntoIterator<Item = Element<Self::NodeWeight, Self::EdgeWeight>>,
{
from_elements_indexable(iterable)
}
}
pub trait ElementIterator<N, E>: Iterator<Item = Element<N, E>> {
fn filter_elements<F>(self, f: F) -> FilterElements<Self, F>
where
Self: Sized,
F: FnMut(Element<&mut N, &mut E>) -> bool,
{
FilterElements {
iter: self,
node_index: 0,
map: Vec::new(),
f,
}
}
}
impl<N, E, I: ?Sized> ElementIterator<N, E> for I where I: Iterator<Item = Element<N, E>> {}
pub struct FilterElements<I, F> {
iter: I,
node_index: usize,
map: Vec<usize>,
f: F,
}
impl<I, F, N, E> Iterator for FilterElements<I, F>
where
I: Iterator<Item = Element<N, E>>,
F: FnMut(Element<&mut N, &mut E>) -> bool,
{
type Item = Element<N, E>;
fn next(&mut self) -> Option<Self::Item> {
loop {
let mut elt = match self.iter.next() {
None => return None,
Some(elt) => elt,
};
let keep = (self.f)(match elt {
Element::Node { ref mut weight } => Element::Node { weight },
Element::Edge {
source,
target,
ref mut weight,
} => Element::Edge {
source,
target,
weight,
},
});
let is_node = if let Element::Node { .. } = elt {
true
} else {
false
};
if !keep && is_node {
self.map.push(self.node_index);
}
if is_node {
self.node_index += 1;
}
if !keep {
continue;
}
match elt {
Element::Edge {
ref mut source,
ref mut target,
..
} => {
match self.map.binary_search(source) {
Ok(_) => continue,
Err(i) => *source -= i,
}
match self.map.binary_search(target) {
Ok(_) => continue,
Err(i) => *target -= i,
}
}
Element::Node { .. } => {}
}
return Some(elt);
}
}
}