use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostingListDirectory {
pub entries: Vec<PostingListEntry>,
pub centroid_to_posting: HashMap<u32, u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PostingListEntry {
pub cluster_id: u32,
pub centroid_id: u32,
pub disk_offset: u64,
pub size_bytes: u32,
pub num_vectors: u32,
pub avg_norm: f32,
}
impl PostingListDirectory {
pub fn new() -> Self {
Self {
entries: Vec::new(),
centroid_to_posting: HashMap::new(),
}
}
pub fn add_entry(&mut self, entry: PostingListEntry) {
let posting_id = self.entries.len() as u32;
self.centroid_to_posting
.insert(entry.centroid_id, posting_id);
self.entries.push(entry);
}
pub fn get_posting_id(&self, centroid_id: u32) -> Option<u32> {
self.centroid_to_posting.get(¢roid_id).copied()
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn memory_size(&self) -> usize {
self.entries.len() * std::mem::size_of::<PostingListEntry>()
+ self.centroid_to_posting.len() * (std::mem::size_of::<u32>() * 2)
}
}
impl Default for PostingListDirectory {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_directory_operations() {
let mut dir = PostingListDirectory::new();
assert!(dir.is_empty());
assert_eq!(dir.len(), 0);
let entry = PostingListEntry {
cluster_id: 0,
centroid_id: 42,
disk_offset: 0,
size_bytes: 1024,
num_vectors: 100,
avg_norm: 1.5,
};
dir.add_entry(entry);
assert!(!dir.is_empty());
assert_eq!(dir.len(), 1);
assert_eq!(dir.get_posting_id(42), Some(0));
assert_eq!(dir.get_posting_id(99), None);
}
}