gamma 0.9.0

Graph primitives and traversals for Rust.
Documentation
use std::collections::{ HashMap, HashSet };
use std::collections::hash_map::Entry::{ Occupied, Vacant };

pub struct Marker {
    nodes: HashSet<usize>,
    edges: HashMap<usize, Vec<usize>>
}

impl Marker {
    pub fn new() -> Self {
        Self {
            nodes: HashSet::new(),
            edges: HashMap::new()
        }
    }

    pub fn mark_node(&mut self, id: usize) {
        if !self.nodes.insert(id) {
            panic!("node marked twice: {}", id)
        }
    }

    pub fn has_node(&self, id: usize) -> bool {
        self.nodes.contains(&id)
    }

    pub fn mark_edge(&mut self, sid: usize, tid: usize) {
        match self.edges.entry(sid) {
            Occupied(mut entry) => {
                if entry.get().contains(&tid) {
                    panic!("edge marked twice: ({},{})", sid, tid)
                } else {
                    entry.get_mut().push(tid)
                }
            },
            Vacant(entry) => {
                entry.insert(vec![ tid ]);
            }
        }

        match self.edges.entry(tid) {
            Occupied(mut entry) => {
                entry.get_mut().push(sid)
            },
            Vacant(entry) => {
                entry.insert(vec![ sid ]);
            }
        }
    }

    pub fn has_edge(&self, sid: usize, tid: usize) -> bool {
        match self.edges.get(&sid) {
            None => false,
            Some(neighbors) => neighbors.contains(&tid)
        }
    }
}

#[cfg(test)]
mod mark_node {
    use super::*;

    #[test]
    #[should_panic(expected="node marked twice: 0")]
    fn duplicate() {
        let mut marker = Marker::new();

        marker.mark_node(0);
        marker.mark_node(0);
    }
}

#[cfg(test)]
mod mark_edge {
    use super::*;

    #[test]
    #[should_panic(expected="edge marked twice: (0,1)")]
    fn duplicate() {
        let mut marker = Marker::new();

        marker.mark_edge(0, 1);
        marker.mark_edge(0, 1);
    }

    #[test]
    #[should_panic(expected="edge marked twice: (1,0)")]
    fn duplicate_reverse() {
        let mut marker = Marker::new();

        marker.mark_edge(0, 1);
        marker.mark_edge(1, 0);
    }
}

#[cfg(test)]
mod has_node {
    use super::*;

    #[test]
    fn outside() {
        let marker = Marker::new();

        assert_eq!(marker.has_node(0), false)
    }

    #[test]
    fn inside() {
        let mut marker = Marker::new();

        marker.mark_node(0);

        assert_eq!(marker.has_node(0), true)
    }
}

#[cfg(test)]
mod has_edge {
    use super::*;

    #[test]
    fn outside() {
        let marker = Marker::new();

        assert_eq!(marker.has_edge(0, 1), false);
    }

    #[test]
    fn inside() {
        let mut marker = Marker::new();

        marker.mark_edge(0, 1);

        assert_eq!(marker.has_edge(0, 1), true);
    }

    #[test]
    fn inside_reverse() {
        let mut marker = Marker::new();

        marker.mark_edge(0, 1);

        assert_eq!(marker.has_edge(1, 0), true);
    }
}