use crate::mapper_impls::hasher::{get_hasher, HashCacher};
use crate::mappers::identity::IdentityMapperWithCustomCacheKey;
use crate::mappers::CachedMapper;
use crate::{CachedMapper, Expression};
use hashbrown::HashMap;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
struct HashedExpression {
expr: Rc<Expression>,
hashval: u64,
}
impl Hash for HashedExpression {
fn hash<H: Hasher>(&self, state: &mut H) {
self.hashval.hash(state)
}
}
impl PartialEq for HashedExpression {
fn eq(&self, other: &Self) -> bool {
self.hashval == other.hashval && self.expr == other.expr
}
}
impl Eq for HashedExpression {}
#[derive(CachedMapper)]
struct Deduplicator {
hasher: HashCacher,
cache: HashMap<HashedExpression, Rc<Expression>>,
}
impl IdentityMapperWithCustomCacheKey for Deduplicator {
type CacheKey = HashedExpression;
fn get_cache_key(&self, expr: Rc<Expression>) -> HashedExpression {
HashedExpression { expr: expr.clone(),
hashval: self.hasher.get(expr.clone()) }
}
}
pub fn deduplicate_nodes(expr: &Expression) -> Rc<Expression> {
let rc_expr = Rc::new(expr.clone());
let hasher = get_hasher(rc_expr.clone());
let mut mapper = Deduplicator { hasher: hasher,
cache: HashMap::new() };
mapper.visit(rc_expr.clone())
}