use std::collections::HashMap;
use uni_common::core::id::{DenseIdx, Vid};
#[derive(Debug, Clone, Default)]
pub struct VidRemapper {
vid_to_dense: HashMap<Vid, DenseIdx>,
dense_to_vid: Vec<Vid>,
}
impl VidRemapper {
pub fn new() -> Self {
Self {
vid_to_dense: HashMap::new(),
dense_to_vid: Vec::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
vid_to_dense: HashMap::with_capacity(capacity),
dense_to_vid: Vec::with_capacity(capacity),
}
}
pub fn insert(&mut self, vid: Vid) -> DenseIdx {
if let Some(&idx) = self.vid_to_dense.get(&vid) {
return idx;
}
let idx = DenseIdx::new(self.dense_to_vid.len() as u32);
self.dense_to_vid.push(vid);
self.vid_to_dense.insert(vid, idx);
idx
}
pub fn insert_many(&mut self, vids: &[Vid]) -> Vec<DenseIdx> {
vids.iter().map(|&vid| self.insert(vid)).collect()
}
pub fn to_dense(&self, vid: Vid) -> Option<DenseIdx> {
self.vid_to_dense.get(&vid).copied()
}
pub fn to_dense_unchecked(&self, vid: Vid) -> DenseIdx {
self.vid_to_dense[&vid]
}
pub fn to_vid(&self, idx: DenseIdx) -> Vid {
self.dense_to_vid[idx.as_usize()]
}
pub fn to_vid_opt(&self, idx: DenseIdx) -> Option<Vid> {
self.dense_to_vid.get(idx.as_usize()).copied()
}
pub fn len(&self) -> usize {
self.dense_to_vid.len()
}
pub fn is_empty(&self) -> bool {
self.dense_to_vid.is_empty()
}
pub fn contains(&self, vid: Vid) -> bool {
self.vid_to_dense.contains_key(&vid)
}
pub fn iter(&self) -> impl Iterator<Item = (DenseIdx, Vid)> + '_ {
self.dense_to_vid
.iter()
.enumerate()
.map(|(i, &vid)| (DenseIdx::new(i as u32), vid))
}
pub fn vids(&self) -> impl Iterator<Item = Vid> + '_ {
self.dense_to_vid.iter().copied()
}
pub fn vids_slice(&self) -> &[Vid] {
&self.dense_to_vid
}
pub fn clear(&mut self) {
self.vid_to_dense.clear();
self.dense_to_vid.clear();
}
pub fn memory_usage(&self) -> usize {
self.vid_to_dense.capacity()
* (std::mem::size_of::<Vid>() + std::mem::size_of::<DenseIdx>())
+ self.dense_to_vid.capacity() * std::mem::size_of::<Vid>()
}
}
#[derive(Debug, Clone, Default)]
pub struct EidRemapper {
eid_to_dense: HashMap<uni_common::core::id::Eid, DenseIdx>,
dense_to_eid: Vec<uni_common::core::id::Eid>,
}
impl EidRemapper {
pub fn new() -> Self {
Self {
eid_to_dense: HashMap::new(),
dense_to_eid: Vec::new(),
}
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
eid_to_dense: HashMap::with_capacity(capacity),
dense_to_eid: Vec::with_capacity(capacity),
}
}
pub fn insert(&mut self, eid: uni_common::core::id::Eid) -> DenseIdx {
if let Some(&idx) = self.eid_to_dense.get(&eid) {
return idx;
}
let idx = DenseIdx::new(self.dense_to_eid.len() as u32);
self.dense_to_eid.push(eid);
self.eid_to_dense.insert(eid, idx);
idx
}
pub fn to_dense(&self, eid: uni_common::core::id::Eid) -> Option<DenseIdx> {
self.eid_to_dense.get(&eid).copied()
}
pub fn to_eid(&self, idx: DenseIdx) -> uni_common::core::id::Eid {
self.dense_to_eid[idx.as_usize()]
}
pub fn len(&self) -> usize {
self.dense_to_eid.len()
}
pub fn is_empty(&self) -> bool {
self.dense_to_eid.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_vid_remapper_basic() {
let mut remapper = VidRemapper::new();
let vid1 = Vid::new(100);
let vid2 = Vid::new(500);
let vid3 = Vid::new(200);
let idx1 = remapper.insert(vid1);
let idx2 = remapper.insert(vid2);
let idx3 = remapper.insert(vid3);
assert_eq!(idx1.as_u32(), 0);
assert_eq!(idx2.as_u32(), 1);
assert_eq!(idx3.as_u32(), 2);
assert_eq!(remapper.to_vid(idx1), vid1);
assert_eq!(remapper.to_vid(idx2), vid2);
assert_eq!(remapper.to_vid(idx3), vid3);
assert_eq!(remapper.to_dense(vid1), Some(idx1));
assert_eq!(remapper.to_dense(vid2), Some(idx2));
assert_eq!(remapper.to_dense(Vid::new(999)), None);
}
#[test]
fn test_vid_remapper_duplicate_insert() {
let mut remapper = VidRemapper::new();
let vid = Vid::new(42);
let idx1 = remapper.insert(vid);
let idx2 = remapper.insert(vid);
assert_eq!(idx1, idx2);
assert_eq!(remapper.len(), 1);
}
#[test]
fn test_vid_remapper_insert_many() {
let mut remapper = VidRemapper::new();
let vids = vec![Vid::new(10), Vid::new(20), Vid::new(30)];
let indices = remapper.insert_many(&vids);
assert_eq!(indices.len(), 3);
assert_eq!(remapper.len(), 3);
for (idx, vid) in indices.iter().zip(vids.iter()) {
assert_eq!(remapper.to_vid(*idx), *vid);
}
}
#[test]
fn test_vid_remapper_iter() {
let mut remapper = VidRemapper::new();
remapper.insert(Vid::new(100));
remapper.insert(Vid::new(200));
remapper.insert(Vid::new(300));
let pairs: Vec<_> = remapper.iter().collect();
assert_eq!(pairs.len(), 3);
assert_eq!(pairs[0], (DenseIdx::new(0), Vid::new(100)));
assert_eq!(pairs[1], (DenseIdx::new(1), Vid::new(200)));
assert_eq!(pairs[2], (DenseIdx::new(2), Vid::new(300)));
}
}