use crate::{index::GenerationalIndex, Error};
use std::collections::{HashMap, VecDeque};
pub struct LightVecAllocator {
loan: usize,
generations: HashMap<usize, usize>,
free: VecDeque<usize>,
}
impl LightVecAllocator {
fn with_capacity(capacity: usize) -> LightVecAllocator {
let mut gens: HashMap<usize, usize> = HashMap::with_capacity(capacity);
for i in 0..capacity {
gens.insert(i, 0);
}
LightVecAllocator {
loan: 1,
generations: gens,
free: VecDeque::with_capacity(capacity),
}
}
fn match_generation(&self, index: &GenerationalIndex) -> bool {
self.generations[&index.index()] == index.generation()
}
fn allocate(&mut self, vec_len: usize) -> GenerationalIndex {
if let Some(idx) = self.free.pop_front() {
GenerationalIndex::new(idx, self.generations[&idx])
} else {
self.generations.reserve(self.loan);
self.generations.insert(vec_len, 0);
self.free.reserve(self.loan);
GenerationalIndex::new(vec_len, 0)
}
}
fn deallocate(&mut self, index: GenerationalIndex) -> Result<(), Error> {
if self.generations[&index.index()] == index.generation() {
let x = self.generations.get_mut(&index.index()).unwrap();
self.free.push_back(index.index());
*x += 1;
Ok(())
} else {
Err(Error::WrongGeneration)
}
}
pub fn set_loan(&mut self, loan: usize) {
self.loan = loan;
}
pub fn loan(&self) -> usize {
self.loan
}
}
pub struct LightVec<T>(Vec<T>);
impl<T> LightVec<T> {
pub fn with_capacity(capacity: usize) -> (LightVec<T>, LightVecAllocator) {
(
LightVec(Vec::with_capacity(capacity)),
LightVecAllocator::with_capacity(capacity),
)
}
pub fn get(&self, index: &GenerationalIndex, allocator: &LightVecAllocator) -> Option<&T> {
if allocator.match_generation(index) {
self.0.get(index.index())
} else {
None
}
}
pub fn insert(&mut self, value: T, allocator: &mut LightVecAllocator) -> GenerationalIndex {
let temp_idx = allocator.allocate(self.0.len());
self.0.insert(temp_idx.index(), value);
temp_idx
}
pub fn remove(
&mut self,
index: GenerationalIndex,
allocator: &mut LightVecAllocator,
) -> Result<(), Error> {
if let Some(_val) = self.0.get(index.index()) {
allocator.deallocate(index)?;
self.0.remove(index.index());
Ok(())
} else {
Err(Error::ElementNotFound)
}
}
}