gdsl 0.2.1

GDSL is a graph data-structure library including graph containers, connected node strutures and efficient algorithms on those structures. Nodes are independent of a graph container and can be used as connected smart pointers.
Documentation
use super::{method::*, path::*, *};
use ahash::AHashSet as HashSet;
use std::{collections::VecDeque, fmt::Display, hash::Hash};

pub struct Bfs<'a, K, N, E>
where
    K: Clone + Hash + Display + PartialEq + Eq,
    N: Clone,
    E: Clone,
{
    root: Node<K, N, E>,
    target: Option<K>,
    method: Method<'a, K, N, E>,
}

impl<'a, K, N, E> Bfs<'a, K, N, E>
where
    K: Clone + Hash + Display + PartialEq + Eq,
    N: Clone,
    E: Clone,
{
    pub fn new(root: &Node<K, N, E>) -> Self {
        Bfs {
            root: root.clone(),
            target: None,
            method: Method::Empty,
        }
    }

    pub fn target(mut self, target: &'a K) -> Self {
        self.target = Some(target.clone());
        self
    }

    pub fn for_each(mut self, f: ForEach<'a, K, N, E>) -> Self {
        self.method = Method::ForEach(f);
        self
    }

    pub fn filter(mut self, f: Filter<'a, K, N, E>) -> Self {
        self.method = Method::Filter(f);
        self
    }

    fn loop_adjacent(
        &mut self,
        result: &mut Vec<Edge<K, N, E>>,
        visited: &mut HashSet<K>,
        queue: &mut VecDeque<Node<K, N, E>>,
    ) -> bool {
        while let Some(node) = queue.pop_front() {
            for edge in node.iter() {
                if self.method.exec(&edge) {
                    let v = edge.target().clone();
                    if !visited.contains(v.key()) {
                        visited.insert(v.key().clone());
                        result.push(edge);
                        if let Some(ref t) = self.target {
                            if v.key() == t {
                                return true;
                            }
                        }
                        queue.push_back(v.clone());
                    }
                }
            }
        }
        false
    }

    fn loop_adjacent_find(
        &mut self,
        visited: &mut HashSet<K>,
        queue: &mut VecDeque<Node<K, N, E>>,
    ) -> Option<Node<K, N, E>> {
        while let Some(node) = queue.pop_front() {
            for edge in node.iter() {
                if self.method.exec(&edge) {
                    let v = edge.target();
                    if !visited.contains(v.key()) {
                        visited.insert(v.key().clone());
                        if let Some(ref t) = self.target {
                            if v.key() == t {
                                return Some(v.clone());
                            }
                        }
                        queue.push_back(v.clone());
                    }
                }
            }
        }
        None
    }

    pub fn search(&'a mut self) -> Option<Node<K, N, E>> {
        let mut queue = VecDeque::new();
        let mut visited = HashSet::default();

        queue.push_back(self.root.clone());
        visited.insert(self.root.key().clone());

        self.loop_adjacent_find(&mut visited, &mut queue)
    }

    pub fn search_cycle(&'a mut self) -> Option<Path<K, N, E>> {
        let mut edges = vec![];
        let mut queue = VecDeque::new();
        let mut visited = HashSet::default();

        self.target = Some(self.root.key().clone());
        queue.push_back(self.root.clone());

        if self.loop_adjacent(&mut edges, &mut visited, &mut queue) {
            Some(Path::from_edge_tree(edges))
        } else {
            None
        }
    }

    pub fn search_path(&mut self) -> Option<Path<K, N, E>> {
        let mut edges = vec![];
        let mut queue = VecDeque::new();
        let mut visited = HashSet::default();

        queue.push_back(self.root.clone());
        visited.insert(self.root.key().clone());

        if self.loop_adjacent(&mut edges, &mut visited, &mut queue) {
            Some(Path::from_edge_tree(edges))
        } else {
            None
        }
    }
}