use diskann::{
graph::{SearchOutputBuffer, glue},
neighbor::Neighbor,
provider::BuildQueryComputer,
};
pub(crate) trait AsDeletionCheck {
type Checker: DeletionCheck;
fn as_deletion_check(&self) -> &Self::Checker;
}
pub(crate) trait DeletionCheck {
fn deletion_check(&self, id: u32) -> bool;
}
#[derive(Debug, Clone, Copy, Default)]
pub struct RemoveDeletedIdsAndCopy;
impl<A, T> glue::SearchPostProcess<A, T> for RemoveDeletedIdsAndCopy
where
A: BuildQueryComputer<T, Id = u32> + AsDeletionCheck,
{
type Error = std::convert::Infallible;
fn post_process<I, B>(
&self,
accessor: &mut A,
_query: T,
_computer: &<A as BuildQueryComputer<T>>::QueryComputer,
candidates: I,
output: &mut B,
) -> impl std::future::Future<Output = Result<usize, Self::Error>> + Send
where
I: Iterator<Item = Neighbor<u32>> + Send,
B: SearchOutputBuffer<u32> + Send + ?Sized,
{
let checker = accessor.as_deletion_check();
let count = output.extend(candidates.filter_map(|n| {
if checker.deletion_check(n.id) {
None
} else {
Some((n.id, n.distance))
}
}));
std::future::ready(Ok(count))
}
}