use std::collections::VecDeque;
use ahash::AHashSet;
use super::budget::{Budget, Stop, Walk};
use crate::value::EntityId;
pub fn breadth_first(
start: EntityId,
budget: Budget,
mut successors: impl FnMut(EntityId) -> Vec<EntityId>,
) -> Walk {
let mut visited = Vec::new();
let mut seen = AHashSet::new();
let mut revisited = Vec::new();
let mut queue = VecDeque::from([(start, 0usize)]);
let mut stop = Stop::Exhausted;
while let Some((node, depth)) = queue.pop_front() {
if !seen.insert(node) {
revisited.push(node);
continue;
}
if visited.len() >= budget.max_nodes {
stop = Stop::NodeLimit;
break;
}
visited.push(node);
if depth >= budget.max_depth {
stop = Stop::DepthLimit;
continue;
}
for successor in successors(node) {
queue.push_back((successor, depth + 1));
}
}
revisited.sort_unstable();
revisited.dedup();
Walk {
visited,
stop,
revisited,
}
}