use crate::error::VectorError;
use super::super::types::NodeStorage;
use super::state::HnswIndex;
impl HnswIndex {
pub fn get_vector(&self, id: u32) -> Option<&[f32]> {
debug_assert!(
self.params.dtype == nodedb_types::vector_dtype::VectorStorageDtype::F32,
"get_vector: called on non-F32 index (dtype={}); use get_vector_bytes instead",
self.params.dtype,
);
self.nodes
.get(id as usize)
.and_then(|n| n.storage.as_f32_slice())
}
pub fn get_vector_bytes(&self, id: u32) -> Option<&[u8]> {
self.nodes.get(id as usize).map(|n| n.storage.as_bytes())
}
#[cfg(not(target_arch = "wasm32"))]
pub fn get_vector_or_backing(&self, id: u32) -> Option<std::borrow::Cow<'_, [f32]>> {
use std::borrow::Cow;
let node = self.nodes.get(id as usize)?;
match &node.storage {
NodeStorage::F32(v) if !v.is_empty() => Some(Cow::Borrowed(v.as_slice())),
NodeStorage::Bytes { bytes, dtype } if !bytes.is_empty() => {
crate::dtype::cast_to_f32(bytes, *dtype, self.dim)
.ok()
.map(Cow::Owned)
}
NodeStorage::F32(_) | NodeStorage::Bytes { .. } => self
.backing
.as_ref()
.and_then(|b| b.get_vector(id))
.map(Cow::Borrowed),
}
}
pub fn materialize_vector(&self, id: u32) -> Result<Vec<f32>, VectorError> {
let node = self
.nodes
.get(id as usize)
.ok_or(VectorError::VectorUnavailable { id })?;
let local = match &node.storage {
NodeStorage::F32(v) if !v.is_empty() => Some(v.clone()),
NodeStorage::Bytes { bytes, dtype } if !bytes.is_empty() => Some(
crate::dtype::cast_to_f32(bytes, *dtype, self.dim).map_err(|e| {
VectorError::VectorDecodeFailed {
id,
detail: e.to_string(),
}
})?,
),
NodeStorage::F32(_) | NodeStorage::Bytes { .. } => None,
};
let vector = match local {
Some(v) => v,
None => self.backing_vector(id)?,
};
if vector.len() != self.dim {
return Err(VectorError::StoredDimensionMismatch {
expected: self.dim,
got: vector.len(),
});
}
Ok(vector)
}
pub fn extract_vectors_and_surrogates(&self) -> Result<(Vec<Vec<f32>>, Vec<u64>), VectorError> {
Ok((self.export_vectors()?, Vec::new()))
}
pub fn export_vectors(&self) -> Result<Vec<Vec<f32>>, VectorError> {
(0..self.nodes.len() as u32)
.map(|id| self.materialize_vector(id))
.collect()
}
}