digraph-rs 0.1.0

a handful of algorithms for digraphs
Documentation
#[macro_export]
macro_rules! extend_nodes {
    ($graph:ident => [$(($id:expr, $p:expr)),+ $(,)?]) => {{
         $(
            $graph.add_node($id,$p);
         )+
        $graph
    }};

    ($graph:ident => [$($id:expr),+ $(,)?]) => {{
         $(
            $graph.add_bare_node($id);
         )+
      $graph
    }};
}

#[macro_export]
macro_rules! extend_edges {
    ($graph:expr => {}) => {{
       $graph
    }};

    ($graph:expr => {[$(($from:expr,$p:expr)),+ $(,)?] => $to:expr; $($rest:tt)*}) => {{
        $(
            $graph.add_edge($from,$to,$p);
         )+
       extend_edges!($graph => {$($rest)*})
    }};

    ($graph:expr => {[$(($from:expr,$p:expr)),+ $(,)?] => $to:expr $(;)?}) => {{
         $(
            $graph.add_edge($from,$to,$p);
         )+
       $graph
    }};
    ($graph:expr => {[$($from:expr),+ $(,)?] => ($to:expr,$p:expr) $(;)?}) => {{

         $(
            $graph.add_edge($from,$to,$p);
          )+

       $graph
    }};
    ($graph:expr => {[$($from:expr),+ $(,)?] => ($to:expr,$p:expr) ; $($rest:tt)*}) => {{

         $(
            $graph.add_edge($from,$to,$p);
          )+

        extend_edges!($graph => {$($rest)*})
    }};
    ($graph:expr => {[$($from:expr),+ $(,)?] => $to:expr $(;)?}) => {{
         $(
           $graph.add_bare_edge($from,$to);
         )+
        $graph
    }};
    ($graph:expr => {[$($from:expr),+ $(,)?] => $to:expr ; $($rest:tt)*}) => {{
         $(
           $graph.add_bare_edge($from,$to);
         )+
         extend_edges!($graph => {$($rest)*})
    }};

    ($graph:expr => {$from:expr => [$(($to:expr,$p:expr)),+ $(,)?] $(;)? }) => {{
         $(
           $graph.add_edge($from,$to,$p);
         )+
         $graph
    }};
    ($graph:expr => {$from:expr => [$(($to:expr,$p:expr)),+ $(,)?] ; $($rest:tt)*}) => {{
         $(
           $graph.add_edge($from,$to,$p);
         )+
          extend_edges!($graph => {$($rest)*})
    }};
    ($graph:expr => {$from:expr => [$($to:expr),+ $(,)?] $(;)?}) => {{
         $(
           $graph.add_bare_edge($from,$to);
         )+
         $graph
    }};
    ($graph:expr => {$from:expr => [$($to:expr),+ $(,)?] ; $($rest:tt)*}) => {{
         $(
           $graph.add_bare_edge($from,$to);
         )+
         extend_edges!($graph => {$($rest)*})
    }};

    ($graph:expr => {$from:expr => ($to:expr,$p:expr) $(;)?}) => {{
         $graph.add_edge($from,$to,$p);
         $graph
    }};
    ($graph:expr => {$from:expr => ($to:expr,$p:expr); $($rest:tt)*}) => {{
         $graph.add_edge($from,$to,$p);
         extend_edges!($graph => {$($rest)*})
    }};
    ($graph:expr => {$from:expr => $to:expr $(;)?}) => {{
         $graph.add_bare_edge($from,$to);
         $graph
    }};
    ($graph:expr => {$from:expr => $to:expr; $($rest:tt)*}) => {{
         $graph.add_bare_edge($from,$to);
         extend_edges!($graph => {$($rest)*})
    }};
}

#[macro_export]
macro_rules! digraph {
    () => {
        DiGraph::empty()
    };

    (_ , $n:ty,_ ) => {
        DiGraph::<usize,$n,EmptyPayload>::new()
    };
   ( $id:ty,_,_) => {
      DiGraph::<$id,EmptyPayload,EmptyPayload>::new()
    };
    ( _,_,$e:ty) => {
        DiGraph::<usize,EmptyPayload,$e>::new()
    };
    ( _, $n:ty, $e:ty) => {
        DiGraph::<usize,$n,$e>::new()
    };

    ( $id:ty,_, $e:ty) => {
        DiGraph::<$id,EmptyPayload,$e>::new()
    };

    ( $id:ty,$n:ty, $e:ty) => {
        DiGraph::<$id,$n,$e>::new()
    };

    (($($tps:tt)+) => $nodes:tt ) => {{
       let mut g = digraph!($($tps)+);
       extend_nodes!(g => $nodes)
     }};


   (($($tps:tt)+)=> $nodes:tt => $edges:tt) => {{
       let mut g = digraph!($($tps)+);
       let mut g = extend_nodes!(g => $nodes);
       extend_edges!(g => $edges)
     }};


    ( => $nodes:tt ) => {{
       let mut g = digraph!();
       extend_nodes!(g => $nodes)
     }};

    (=> $nodes:tt => $edges:tt) => {{
       let mut g = digraph!();
       let mut g = extend_nodes!(g => $nodes);
       extend_edges!(g => $edges)
     }};

}

#[cfg(test)]
mod tests {
    use crate::digraph;
    use crate::{DiGraph, EmptyPayload};
    use std::collections::HashMap;

    #[derive(Default)]
    struct S(i32);

    impl S {
        pub fn new(i: i32) -> Self {
            Self { 0: i }
        }
    }

    #[test]
    fn simple_macro_v_d_test() {
        let d = digraph!();
        let d = digraph!(_, S, usize);
        let d = digraph!(_, S, S);
        let d = digraph!(_, S, _);
        let d = digraph!(_, _, S);
        let d = digraph!(_, bool, S);
        let d = digraph!(=> [1,2,3]);
        assert_eq!(
            d.nodes,
            HashMap::from([(1, EmptyPayload), (2, EmptyPayload), (3, EmptyPayload)])
        );

        let d = digraph!((_,i32,_) => [(1,1),(2,2),(3,0)]);
        assert_eq!(d.nodes, HashMap::from([(1, 1), (2, 2), (3, 0)]));

        let d = digraph!(
            (_,_,i32) => [1,2,3,4] => {
                1 => 2;
                2 => (3,1);
                [4,3] => 1;
            }
        );
        assert_eq!(
            d.nodes,
            HashMap::from([
                (1, EmptyPayload),
                (2, EmptyPayload),
                (3, EmptyPayload),
                (4, EmptyPayload)
            ])
        );
        assert_eq!(
            d.edges,
            HashMap::from([
                (1, HashMap::from([(2, 0)])),
                (2, HashMap::from([(3, 1)])),
                (3, HashMap::from([(1, 0)])),
                (4, HashMap::from([(1, 0)])),
            ])
        );
    }
    #[test]
    fn simple_diff_key_macro_test() {
        let d = digraph!(String, _, _);
        let d = digraph!((&str,_,_) => ["1","2","3"]);
        assert_eq!(
            d.nodes,
            HashMap::from([
                ("1", EmptyPayload),
                ("2", EmptyPayload),
                ("3", EmptyPayload)
            ])
        );

        let mut g = digraph!((&str,_,i32) => ["a","b","c"] => {
            "a" => "b";
            ["a","b"] => "c";
        });

        let f = g.edges;

        assert_eq!(f.get("a"), Some(&HashMap::from([("b", 0), ("c", 0)])));
        assert_eq!(f.get("b"), Some(&HashMap::from([("c", 0)])));
    }

    #[test]
    fn builder_nodes_test() {
        let mut g = digraph!(_, usize, _);
        let g = extend_nodes!(g => [(1,1),(2,1)]);
        assert_eq!(g.nodes, HashMap::from([(1, 1), (2, 1)]));

        let mut g = digraph!(_, usize, _);
        let def_p = 100;
        let g = extend_nodes!(g => [(1,def_p),(2,def_p)]);
        assert_eq!(g.nodes, HashMap::from([(1, 100), (2, 100)]));
    }

    #[test]
    fn builder_edges_arr_to_test() {
        let mut g = digraph!(_, _, i32);
        let mut g = extend_nodes!(g => [1,2,3,4,5,6,7]);
        let mut g = extend_edges!(g => {
            [(2,1),(3,1)] => 4
        });
        assert_eq!(
            g.edges,
            HashMap::from([(2, HashMap::from([(4, 1)])), (3, HashMap::from([(4, 1)])),])
        );

        let mut g = digraph!(_, _, i32);
        let mut g = extend_nodes!(g => [1,2,3,4,5,6,7]);
        let g = extend_edges!(g => {
            [(4,1),(1,1)] => 5;
            [(5,1),(6,1)] => 7;
        });
        assert_eq!(
            g.edges,
            HashMap::from([
                (4, HashMap::from([(5, 1)])),
                (1, HashMap::from([(5, 1)])),
                (5, HashMap::from([(7, 1)])),
                (6, HashMap::from([(7, 1)])),
            ])
        );

        let mut g = digraph!(_, _, i32);
        let mut g = extend_nodes!(g => [1,2,3,4,5,6,7]);
        let mut g = extend_edges!(g => {
            [1,2] => (3,10)
        });
        assert_eq!(
            g.edges,
            HashMap::from([(2, HashMap::from([(3, 10)])), (1, HashMap::from([(3, 10)])),])
        );

        let mut g = extend_edges!(g => {
            [1,2] => (3,10);
            [3,4] => (5,1);
            [(5,1),(6,10)] => 7
        });
        assert_eq!(
            g.edges,
            HashMap::from([
                (2, HashMap::from([(3, 10)])),
                (1, HashMap::from([(3, 10)])),
                (3, HashMap::from([(5, 1)])),
                (4, HashMap::from([(5, 1)])),
                (5, HashMap::from([(7, 1)])),
                (6, HashMap::from([(7, 10)])),
            ])
        );

        let mut g = digraph!();
        let mut g = extend_nodes!(g => [1,2,3,4,5,6,7]);
        let mut g = extend_edges!(g => {
            [1,2] => 3
        });
        assert_eq!(
            g.edges,
            HashMap::from([
                (2, HashMap::from([(3, EmptyPayload)])),
                (1, HashMap::from([(3, EmptyPayload)])),
            ])
        );
        let mut g = extend_edges!(g => {
            [1,2] => 3;
            [3,4] => 5;
        });
        assert_eq!(
            g.edges,
            HashMap::from([
                (2, HashMap::from([(3, EmptyPayload)])),
                (1, HashMap::from([(3, EmptyPayload)])),
                (3, HashMap::from([(5, EmptyPayload)])),
                (4, HashMap::from([(5, EmptyPayload)])),
            ])
        );

        let mut g = extend_edges!(g => {
            5 => [6,7];
            6 => [7,1];
        });
        assert_eq!(
            g.edges,
            HashMap::from([
                (2, HashMap::from([(3, EmptyPayload)])),
                (1, HashMap::from([(3, EmptyPayload)])),
                (3, HashMap::from([(5, EmptyPayload)])),
                (4, HashMap::from([(5, EmptyPayload)])),
                (5, HashMap::from([(7, EmptyPayload), (6, EmptyPayload)])),
                (6, HashMap::from([(7, EmptyPayload), (1, EmptyPayload)])),
            ])
        );

        let mut g = digraph!(_, _, i32);
        let mut g = extend_nodes!(g => [1,2,3,4,5,6,7]);
        let g = extend_edges!(g => {
            [(1,1),(2,1)] => 3;
            [(3,1)] => 4;
            4 => [(5,1),(6,1)];
            7 => [1,2]

        });
        assert_eq!(
            g.edges,
            HashMap::from([
                (1, HashMap::from([(3, 1)])),
                (2, HashMap::from([(3, 1)])),
                (3, HashMap::from([(4, 1)])),
                (4, HashMap::from([(5, 1), (6, 1)])),
                (7, HashMap::from([(1, 0), (2, 0)])),
            ])
        );
    }

    #[test]
    fn builder_edges_simple_to_test() {
        let mut g = digraph!(_, _, i32);
        let mut g = extend_nodes!(g => [1,2,3,4,5,6,7]);
        let mut g = extend_edges!(g => {
            1 => [1,2];
            2 => 3;
            3 => 4;
            4 => (5,7);
            5 => (6,1);
            7 => 1
        });

        let f = g.edges;

        assert_eq!(f.get(&1), Some(&HashMap::from([(1, 0), (2, 0)])));
        assert_eq!(f.get(&2), Some(&HashMap::from([(3, 0)])));
        assert_eq!(f.get(&3), Some(&HashMap::from([(4, 0)])));
        assert_eq!(f.get(&4), Some(&HashMap::from([(5, 7)])));
        assert_eq!(f.get(&7), Some(&HashMap::from([(1, 0)])));
    }
}