use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Clone)]
pub struct KindIndex {
inner: Arc<RwLock<HashMap<String, Vec<i64>>>>,
}
impl KindIndex {
pub fn new() -> Self {
Self {
inner: Arc::new(RwLock::new(HashMap::new())),
}
}
pub fn insert(&self, kind: String, node_id: i64) {
let mut index = self.inner.write();
index.entry(kind).or_default().push(node_id);
}
pub fn get(&self, kind: &str) -> Vec<i64> {
let index = self.inner.read();
index.get(kind).cloned().unwrap_or_default()
}
pub fn all_kinds(&self) -> Vec<String> {
let index = self.inner.read();
index.keys().cloned().collect()
}
pub fn clear(&self) {
let mut index = self.inner.write();
index.clear();
}
pub fn kind_count(&self) -> usize {
let index = self.inner.read();
index.len()
}
pub fn total_nodes(&self) -> usize {
let index = self.inner.read();
index.values().map(|v| v.len()).sum()
}
pub(crate) fn export(&self) -> HashMap<String, Vec<i64>> {
self.inner.read().clone()
}
pub(crate) fn import(&self, data: HashMap<String, Vec<i64>>) {
let mut index = self.inner.write();
*index = data;
}
}
impl Default for KindIndex {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_insert_and_get() {
let index = KindIndex::new();
index.insert("Function".to_string(), 1);
index.insert("Function".to_string(), 2);
index.insert("Class".to_string(), 3);
assert_eq!(index.get("Function"), vec![1, 2]);
assert_eq!(index.get("Class"), vec![3]);
assert_eq!(index.get("Unknown"), Vec::<i64>::new());
}
#[test]
fn test_clear() {
let index = KindIndex::new();
index.insert("Test".to_string(), 1);
assert_eq!(index.kind_count(), 1);
index.clear();
assert_eq!(index.kind_count(), 0);
}
}