use crate::types::VectorId;
use alloc::vec::Vec;
pub struct VectorIdMap<V> {
entries: Vec<(VectorId, V)>,
sorted_index: Vec<usize>,
}
impl<V> VectorIdMap<V> {
pub const fn new() -> Self {
Self {
entries: Vec::new(),
sorted_index: Vec::new(),
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
fn sorted_search(&self, key: &str) -> Result<usize, usize> {
binary_search_by(&self.sorted_index, |&idx| {
let entry_key: &str = self.entries.get(idx).map_or("", |(k, _)| k.as_ref());
entry_key.cmp(key)
})
}
pub fn contains_key(&self, key: &str) -> bool {
self.sorted_search(key).is_ok()
}
pub fn get(&self, key: &str) -> Option<&V> {
self.sorted_search(key).ok().and_then(|sorted_pos| {
self.sorted_index
.get(sorted_pos)
.and_then(|&entry_idx| self.entries.get(entry_idx).map(|(_, v)| v))
})
}
pub fn insert(&mut self, key: VectorId, value: V) -> bool {
match self.sorted_search(&key) {
Ok(_) => false, Err(sorted_pos) => {
let entry_idx = self.entries.len();
self.entries.push((key, value));
self.sorted_index.insert(sorted_pos, entry_idx);
true
}
}
}
pub fn remove(&mut self, key: &str) -> Option<V> {
match self.sorted_search(key) {
Err(_) => None,
Ok(sorted_pos) => {
let entry_idx = self.sorted_index.remove(sorted_pos);
let (_k, v) = self.entries.remove(entry_idx);
for si in &mut self.sorted_index {
if *si > entry_idx {
*si -= 1;
}
}
Some(v)
}
}
}
pub fn iter(&self) -> impl Iterator<Item = (&VectorId, &V)> {
self.entries.iter().map(|(k, v)| (k, v))
}
}
fn binary_search_by<T, F>(slice: &[T], mut pred: F) -> Result<usize, usize>
where
F: FnMut(&T) -> core::cmp::Ordering,
{
use core::cmp::Ordering;
let mut lo = 0usize;
let mut hi = slice.len();
while lo < hi {
let mid = lo + (hi - lo) / 2;
match slice.get(mid).map_or(Ordering::Greater, &mut pred) {
Ordering::Less => lo = mid + 1,
Ordering::Greater => hi = mid,
Ordering::Equal => return Ok(mid),
}
}
Err(lo)
}