use super::MappedVectorIndex;
use super::format::to_usize;
use crate::error::SearchError;
use crate::hnsw::{Graph, NodeLinks, RoutingIndex, VectorIndex};
use crate::vector::VectorStore;
impl MappedVectorIndex {
pub fn to_owned(&self) -> Result<VectorIndex, SearchError> {
let vectors = VectorStore::from_values(
self.header.config.dimensions,
self.header.config.metric,
self.key_slice().to_vec(),
self.vector_slice().to_vec(),
)?;
let graphs = self.materialize_graphs()?;
let routing = RoutingIndex {
entries: self
.routing_codes()
.iter()
.copied()
.zip(self.routing_nodes().iter().copied())
.collect(),
};
VectorIndex::from_parts(self.header.config.clone(), vectors, graphs, routing)
}
fn materialize_graphs(&self) -> Result<Vec<Graph>, SearchError> {
let mut graphs = Vec::new();
graphs
.try_reserve_exact(self.graphs.len())
.map_err(|_| SearchError::AllocationFailed)?;
for graph in &self.graphs {
let node_layers = graph.node_layers(&self.mapping);
let layer_neighbors = graph.layer_neighbors(&self.mapping);
let neighbors = graph.neighbors(&self.mapping);
let mut nodes = Vec::new();
nodes
.try_reserve_exact(self.len())
.map_err(|_| SearchError::AllocationFailed)?;
for node in 0..self.len() {
let layer_start = to_usize(node_layers[node])?;
let layer_end = to_usize(node_layers[node + 1])?;
let mut layers = Vec::new();
layers
.try_reserve_exact(layer_end.saturating_sub(layer_start))
.map_err(|_| SearchError::AllocationFailed)?;
for layer in layer_start..layer_end {
let start = to_usize(layer_neighbors[layer])?;
let end = to_usize(layer_neighbors[layer + 1])?;
layers.push(neighbors[start..end].to_vec());
}
nodes.push(NodeLinks { layers });
}
graphs.push(Graph {
entry: graph.entry,
max_level: graph.max_level,
nodes,
});
}
Ok(graphs)
}
}