71 lines
2.0 KiB
Rust

use std::collections::HashMap;
use prometeu_analysis::ids::ProjectId;
#[derive(Debug, Clone, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
pub struct ProjectKey {
pub name: String,
pub version: String,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ProjectMeta {
pub id: ProjectId,
pub name: String,
pub version: String,
}
#[derive(Debug, Default, Clone)]
pub struct ProjectRegistry {
by_name: HashMap<ProjectKey, ProjectId>,
projects: Vec<ProjectMeta>,
}
impl ProjectRegistry {
pub fn new() -> Self { Self::default() }
pub fn intern(&mut self, key: &ProjectKey) -> ProjectId {
if let Some(id) = self.by_name.get(key).copied() { return id; }
let id = ProjectId(self.projects.len() as u32);
self.by_name.insert(key.clone(), id);
self.projects.push(ProjectMeta { id, name: key.name.clone(), version: key.version.clone() });
id
}
pub fn meta(&self, id: ProjectId) -> Option<&ProjectMeta> {
self.projects.get(id.as_usize())
}
pub fn key_of(&self, id: ProjectId) -> Option<ProjectKey> {
self.meta(id).map(|m| ProjectKey { name: m.name.clone(), version: m.version.clone() })
}
pub fn len(&self) -> usize { self.projects.len() }
pub fn is_empty(&self) -> bool { self.projects.is_empty() }
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn project_registry_stable_ids_for_same_key() {
let mut reg = ProjectRegistry::new();
let k = ProjectKey { name: "sdk".into(), version: "1.0.0".into() };
let id1 = reg.intern(&k);
let id2 = reg.intern(&k);
assert_eq!(id1, id2);
// Different version -> different id
let k2 = ProjectKey { name: "sdk".into(), version: "1.1.0".into() };
let id3 = reg.intern(&k2);
assert_ne!(id1, id3);
// Meta lookup
let m1 = reg.meta(id1).unwrap();
assert_eq!(m1.name, "sdk");
assert_eq!(m1.version, "1.0.0");
}
}