mapgraph 0.12.0

A directed graph that can also be used as an arbitrary map.
Documentation
use crate::{aliases::SlotMapGraph, graph::iter::EdgesWalker};
use alloc::{vec, vec::Vec};
#[cfg(feature = "rayon")]
use {crate::aliases::BTreeSlotMapGraph, rayon::iter::ParallelIterator};

#[test]
fn test_insert_refs() {
    let v = vec![1, 2, 3];
    let mut graph = SlotMapGraph::<&i32, ()>::default();

    let refs: Vec<_> = v.iter().map(|r| graph.add_node(r)).collect();
    graph.clear();
    drop(graph);
    drop(refs);
}

#[test]
fn test_remove_edge_complex_cyclic() {
    let mut graph = SlotMapGraph::<i32, ()>::default();

    let root = graph.add_node(1);
    let left = graph.add_node(2);
    let right = graph.add_node(3);

    let first_edge = graph.add_edge((), root, left).unwrap();
    let second_edge = graph.add_edge((), root, root).unwrap();
    let third_edge = graph.add_edge((), root, right).unwrap();

    graph.remove_edge(second_edge);

    graph.validate();
    assert_eq!(graph.find_edge(root, left).unwrap(), Some(first_edge));
    assert_eq!(graph.find_edge(root, right).unwrap(), Some(third_edge));
    assert_eq!(graph.edges_count(), 2);

    assert_eq!(graph.unlink_and_remove_node(root), Some(1));
    assert_eq!(graph.edges_count(), 0);
}

#[test]
fn test_drain_edges() {
    let mut graph = SlotMapGraph::<i32, ()>::default();

    let root = graph.add_node(1);
    let left = graph.add_node(2);
    let right = graph.add_node(3);

    let _first_edge = graph.add_edge((), root, left).unwrap();
    let _second_edge = graph.add_edge((), root, root).unwrap();
    let _third_edge = graph.add_edge((), root, right).unwrap();
    let _fourth_edge = graph.add_edge((), right, left).unwrap();
    let _fifth_edge = graph.add_edge((), left, root).unwrap();

    assert_eq!(graph.drain_outgoing_edges(root).count(), 3);
    assert_eq!(graph.drain_outgoing_edges(left).count(), 1);
    assert_eq!(graph.drain_outgoing_edges(right).count(), 1);
    assert!(graph.node(root).unwrap().next_outgoing_edge.is_none());
    assert!(graph.node(left).unwrap().next_outgoing_edge.is_none());
    assert!(graph.node(right).unwrap().next_outgoing_edge.is_none());

    graph.validate();
}

#[test]
fn test_drain_edges_incomplete() {
    let mut graph = SlotMapGraph::<i32, ()>::default();

    let root = graph.add_node(1);
    let left = graph.add_node(2);
    let right = graph.add_node(3);

    let first_edge = graph.add_edge((), root, left).unwrap();
    let second_edge = graph.add_edge((), root, root).unwrap();
    let third_edge = graph.add_edge((), root, right).unwrap();
    let fourth_edge = graph.add_edge((), right, left).unwrap();
    let fifth_edge = graph.add_edge((), left, root).unwrap();

    let mut iter = graph.drain_outgoing_edges(root);
    let _ = iter.next();
    drop(iter);
    graph.validate();
    assert!(graph.is_valid_edge_index(first_edge));
    assert!(graph.is_valid_edge_index(second_edge));
    assert!(!graph.is_valid_edge_index(third_edge));
    assert!(graph.is_valid_edge_index(fourth_edge));
    assert!(graph.is_valid_edge_index(fifth_edge));
    assert_eq!(
        graph.node(root).unwrap().next_outgoing_edge,
        Some(second_edge)
    );

    let mut iter = graph.drain_outgoing_edges(left);
    let _ = iter.next();
    drop(iter);
    graph.validate();
    assert!(graph.is_valid_edge_index(first_edge));
    assert!(graph.is_valid_edge_index(second_edge));
    assert!(!graph.is_valid_edge_index(third_edge));
    assert!(graph.is_valid_edge_index(fourth_edge));
    assert!(!graph.is_valid_edge_index(fifth_edge));
    assert!(graph.node(left).unwrap().next_outgoing_edge.is_none());

    let mut iter = graph.drain_outgoing_edges(right);
    let _ = iter.next();
    drop(iter);
    graph.validate();
    assert!(graph.is_valid_edge_index(first_edge));
    assert!(graph.is_valid_edge_index(second_edge));
    assert!(!graph.is_valid_edge_index(third_edge));
    assert!(!graph.is_valid_edge_index(fourth_edge));
    assert!(!graph.is_valid_edge_index(fifth_edge));
    assert!(graph.node(right).unwrap().next_outgoing_edge.is_none());
}

#[test]
fn test_split_iter() {
    let mut graph = SlotMapGraph::<i32, ()>::default();

    let (nodes, edges) = graph.as_nodes_mut_and_edges();

    for (_, node) in nodes {
        let mut walker = node.walk_outputs();
        while let Some((_index, _edge)) = walker.walk_edges_next(edges) {}
    }
}

#[test]
#[cfg(feature = "rayon")]
fn test_par_split_iter() {
    let mut graph = BTreeSlotMapGraph::<i32, (), i32>::default();

    let (nodes, edges) = graph.as_nodes_mut_and_edges();

    nodes.par_iter_mut().for_each(|(_index, node)| {
        let mut walker = node.walk_outputs();
        while let Some((_index, _edge)) = walker.walk_edges_next(edges) {}
    });
}