use std::{collections::HashSet, fmt::Debug, hash::Hash};
#[derive(Debug, Clone)]
pub struct CycleDetector<T: Clone + Eq + Hash + Debug> {
nodes_in_path: HashSet<T>,
stack: Vec<T>,
}
impl<T: Clone + Eq + Hash + Debug> CycleDetector<T> {
pub fn new() -> Self {
CycleDetector {
nodes_in_path: HashSet::new(),
stack: Vec::new(),
}
}
pub fn enter(&self, node: T) -> Result<Self, T> {
if self.nodes_in_path.contains(&node) {
return Err(node); }
let mut new_nodes = self.nodes_in_path.clone();
new_nodes.insert(node.clone());
let mut new_stack = self.stack.clone();
new_stack.push(node);
Ok(CycleDetector {
nodes_in_path: new_nodes,
stack: new_stack,
})
}
pub fn last(&self) -> Option<&T> {
self.stack.last()
}
}