use crate::config::DistanceMetric;
use crate::error::SearchError;
use crate::mutable::MutableSnapshot;
use crate::quantized::QuantizedIndex;
use crate::vector::squared_norm;
use std::collections::BTreeSet;
pub(super) fn validate_quantized(
snapshot: &MutableSnapshot,
quantized: Option<&QuantizedIndex>,
) -> Result<(), SearchError> {
let Some(quantized) = quantized else {
return Ok(());
};
if quantized.config() != &snapshot.config {
return Err(SearchError::InvalidConfig(
"bundle quantized config differs from mutable config",
));
}
let mut active = snapshot.base.keys().collect::<BTreeSet<_>>();
if let Some(sealed) = &snapshot.sealed {
active.extend(sealed.keys());
}
active.extend(snapshot.pending.keys().copied());
for key in &snapshot.deleted {
active.remove(key);
}
if !active.iter().copied().eq(quantized.keys.iter().copied()) {
return Err(SearchError::InvalidConfig(
"bundle quantized keys differ from active mutable keys",
));
}
Ok(())
}
pub(super) fn validate_prepared(
metric: DistanceMetric,
vector: &[f32],
position: usize,
) -> Result<(), SearchError> {
let norm = squared_norm(vector, Some(position))?;
if metric == DistanceMetric::Cosine && norm == 0.0 {
return Err(SearchError::CorruptSnapshot(
"cosine bundle contains a zero pending vector",
));
}
Ok(())
}