pub const VAMANA_MAGIC: &[u8; 8] = b"NDBVAMAN";
pub const VAMANA_VERSION: u32 = 1;
pub const HEADER_BYTES: u64 = 64;
#[derive(Debug, Clone, PartialEq)]
pub struct VamanaStorageLayout {
pub dim: u32,
pub r: u32,
pub alpha: f32,
pub num_nodes: u64,
pub entry: u64,
pub adjacency_offset: u64,
pub vectors_offset: u64,
}
impl VamanaStorageLayout {
pub fn new(dim: u32, r: u32, alpha: f32, num_nodes: u64, entry: u64) -> Self {
let adjacency_offset = HEADER_BYTES;
let adjacency_bytes = r as u64 * 4 * num_nodes; let vectors_offset = adjacency_offset + adjacency_bytes;
Self {
dim,
r,
alpha,
num_nodes,
entry,
adjacency_offset,
vectors_offset,
}
}
pub fn adjacency_bytes(&self) -> u64 {
self.r as u64 * 4 * self.num_nodes
}
pub fn vectors_bytes(&self) -> u64 {
self.dim as u64 * 4 * self.num_nodes }
}
pub fn vector_offset(layout: &VamanaStorageLayout, idx: u64) -> u64 {
layout.vectors_offset + idx * layout.dim as u64 * 4
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn vector_offset_manual_computation() {
let layout = VamanaStorageLayout::new(4, 64, 1.2, 100, 0);
assert_eq!(layout.adjacency_offset, 64);
assert_eq!(layout.adjacency_bytes(), 25_600);
assert_eq!(layout.vectors_offset, 25_664);
assert_eq!(vector_offset(&layout, 5), 25_744);
}
#[test]
fn vector_offset_idx_zero_equals_vectors_offset() {
let layout = VamanaStorageLayout::new(8, 32, 1.2, 50, 0);
assert_eq!(vector_offset(&layout, 0), layout.vectors_offset);
}
#[test]
fn vectors_bytes_correct() {
let layout = VamanaStorageLayout::new(128, 64, 1.2, 1000, 0);
assert_eq!(layout.vectors_bytes(), 512_000);
}
#[test]
fn magic_bytes_length() {
assert_eq!(VAMANA_MAGIC.len(), 8);
}
}