use std::marker::PhantomData;
use std::sync::Arc;
use super::access::IndexTarget;
use crate::TypedWriteHook;
use crate::key::Key;
pub struct IndexHook<SK, SV, I: IndexTarget, P> {
pub(super) index: Arc<I>,
pub(super) project: P,
pub(super) _pd: PhantomData<fn(&SK, &SV)>,
}
impl<SK, SV, I, P> TypedWriteHook<SK, SV> for IndexHook<SK, SV, I, P>
where
SK: Key,
SV: Send + Sync,
I: IndexTarget,
P: Fn(&SK, &SV) -> (I::K, I::V) + Send + Sync,
{
const NEEDS_OLD_VALUE: bool = true;
const NEEDS_WRITE: bool = true;
const NEEDS_INIT: bool = false;
fn on_write(&self, key: &SK, old: Option<&SV>, new: Option<&SV>) {
let old_p = old.map(|o| (self.project)(key, o));
let new_p = new.map(|n| (self.project)(key, n));
match (old_p, new_p) {
(Some((ok, _)), Some((nk, nv))) => {
if ok.as_bytes() != nk.as_bytes()
&& let Err(e) = self.index.delete_entry(&ok)
{
tracing::error!(error = %e, "index hook: delete old projection failed");
}
if let Err(e) = self.index.put_entry(&nk, &nv) {
tracing::error!(error = %e, "index hook: put projection failed");
}
}
(None, Some((nk, nv))) => {
if let Err(e) = self.index.put_entry(&nk, &nv) {
tracing::error!(error = %e, "index hook: put projection failed");
}
}
(Some((ok, _)), None) => {
if let Err(e) = self.index.delete_entry(&ok) {
tracing::error!(error = %e, "index hook: delete projection failed");
}
}
(None, None) => {}
}
}
}