#[cfg(test)]
mod hash_one_ext;
#[cfg(feature = "hashbrown")]
pub mod hashbrown;
use std::{
collections::{hash_map::DefaultHasher, HashSet},
hash::{BuildHasher, Hasher},
};
use super::Identifiable;
pub type HashSetVisitor = HashSet<usize>;
pub trait Visitor {
type Hasher: Hasher;
fn visit<N>(&mut self, node: &N) -> bool
where
N: Identifiable;
fn clear(&mut self);
fn touch<N>(&mut self, _node: &N, _operation: Option<&'static str>)
where
N: Identifiable,
{
}
fn notify_recalculated<N>(&mut self, _node: &N)
where
N: Identifiable,
{
}
fn touch_dependency_group(&mut self, _dep: &'static str) {}
fn leave<N>(&mut self, _node: &N)
where
N: Identifiable,
{
}
fn hasher(&self) -> Self::Hasher;
}
impl Visitor for HashSetVisitor {
type Hasher = DefaultHasher;
fn visit<N>(&mut self, node: &N) -> bool
where
N: Identifiable,
{
self.insert(node.id())
}
fn clear(&mut self) {
self.clear()
}
fn hasher(&self) -> Self::Hasher {
HashSetVisitor::hasher(self).build_hasher()
}
}
#[derive(Debug, Clone, Default)]
pub struct DiagnosticVisitor {
pub visitor: HashSetVisitor,
pub recalculated: HashSet<usize>,
}
impl Visitor for DiagnosticVisitor {
type Hasher = DefaultHasher;
fn visit<N>(&mut self, node: &N) -> bool
where
N: Identifiable,
{
self.visitor.visit(node)
}
fn clear(&mut self) {
self.visitor.clear();
self.recalculated.clear();
}
fn hasher(&self) -> Self::Hasher {
<HashSetVisitor as Visitor>::hasher(&self.visitor)
}
fn notify_recalculated<N>(&mut self, node: &N)
where
N: Identifiable,
{
self.recalculated.insert(node.id());
}
}
impl DiagnosticVisitor {
#[allow(unused)]
pub fn new() -> Self {
Self::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::execution::visitor::hash_one_ext::hash_one;
#[test]
fn test_visitor_hasher() {
let visitor = HashSetVisitor::default();
let hasher_a = visitor.hasher();
let hasher_b = visitor.hasher();
assert_eq!(hash_one(hasher_a, 123), hash_one(hasher_b, 123));
}
}