#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] pub struct GenerationalIndex { index: usize, generation: u64, } impl GenerationalIndex { pub fn index(&self) -> usize { self.index } pub fn generation(&self) -> u64 { self.generation } } struct AllocatorEntry { is_live: bool, generation: u64, } pub struct GenerationalIndexAllocator { entries: Vec, free: Vec, } impl GenerationalIndexAllocator { pub fn allocate(&mut self) -> GenerationalIndex { match self.free.pop() { Some(index) =>{ self.entries[index].generation += 1; self.entries[index].is_live = true; GenerationalIndex { index, generation: self.entries[index].generation, } }, None => { self.entries.push(AllocatorEntry { is_live: true, generation: 0, }); GenerationalIndex { index: self.entries.len() -1, generation: 0, } } } } // Returns true if the index was allocated before and is now deallocated pub fn deallocate(&mut self, index: GenerationalIndex) -> bool { if self.is_live(index) { self.entries[index.index()].is_live = false; self.free.push(index.index()); true } else { false } } pub fn is_live(&self, index: GenerationalIndex) -> bool { index.index() < self.entries.len() && self.entries[index.index()].generation == index.generation && self.entries[index.index()].is_live } } struct ArrayEntry { value: T, generation: u64, } pub struct GenerationalIndexArray(Vec>>); impl GenerationalIndexArray { pub fn set(&mut self, index: GenerationalIndex, value: T) { while self.0.len() <= index.index() { self.0.push(None); } let previous_generation = match &self.0[index.index()] { Some(entry) => entry.generation, None => 0, }; if previous_generation > index.generation() { panic!("write an index from previous gen"); } self.0[index.index()] = Some(ArrayEntry { value, generation: index.generation(), }); } pub fn remove(&mut self, index: GenerationalIndex) { if index.index() < self.0.len() { self.0[index.index()] = None; } } pub fn get(&self, index: GenerationalIndex) -> Option<&T> { if index.index() >= self.0.len() { return None; } match &self.0[index.index()] { Some(entry) => if entry.generation == index.generation() { Some(&entry.value) } else { None }, None => None } } pub fn get_mut(&mut self, index: GenerationalIndex) -> Option<&mut T> { if index.index() >= self.0.len() { return None; } match &mut self.0[index.index()] { Some(entry) => if entry.generation == index.generation() { Some(&mut entry.value) } else { None }, None => None } } }