use super::GenerationCounterT;
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
pub struct GenerationIndex(GenerationCounterT);
pub struct Generation<T> {
generation_index: GenerationIndex,
value: Option<T>,
}
impl<T> Generation<T> {
pub fn new() -> Self {
Generation {
generation_index: GenerationIndex(0),
value: None,
}
}
pub fn get(&self, generation: GenerationIndex) -> Option<&T> {
let value = self.value.as_ref()?;
if self.generation_index == generation {
Some(value)
} else {
None
}
}
pub fn get_mut(&mut self, generation: GenerationIndex) -> Option<&mut T> {
let value = self.value.as_mut()?;
if self.generation_index == generation {
Some(value)
} else {
None
}
}
pub fn allocate(&mut self, value: T) -> GenerationIndex {
assert!(
self.value.is_none(),
"Can only allocate a generation if it's not already allocated"
);
self.value = Some(value);
self.generation_index
}
pub fn free(&mut self, generation_index: GenerationIndex) {
assert!(
self.value.is_some(),
"Can only free a generation if it's not already freed"
);
assert!(
self.generation_index == generation_index,
"Can not free a generation with incorrect generation_index"
);
self.value = None;
self.generation_index.0 += 1;
}
pub fn is_none(&self) -> bool {
self.value.is_none()
}
pub fn peek(&self) -> Option<&T> {
self.value.as_ref()
}
pub fn peek_mut(&mut self) -> Option<&mut T> {
self.value.as_mut()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_generation_get() {
let mut value = Generation::new();
assert!(value.get(GenerationIndex(0)).is_none());
let generation_index0 = value.allocate(0);
assert!(value.get(generation_index0).is_some());
value.free(generation_index0);
assert!(value.get(generation_index0).is_none());
let generation_index1 = value.allocate(0);
assert!(value.get(generation_index0).is_none());
assert!(value.get(generation_index1).is_some());
}
#[test]
fn test_generation_get_mut() {
let mut value = Generation::new();
assert!(value.get_mut(GenerationIndex(0)).is_none());
let generation_index0 = value.allocate(0);
assert!(value.get_mut(generation_index0).is_some());
value.free(generation_index0);
assert!(value.get_mut(generation_index0).is_none());
let generation_index1 = value.allocate(0);
assert!(value.get_mut(generation_index0).is_none());
assert!(value.get_mut(generation_index1).is_some());
}
#[test]
#[should_panic(expected = "Can only allocate a generation if it's not already allocated")]
fn test_double_allocate() {
let mut value = Generation::new();
value.allocate(0);
value.allocate(0);
}
#[test]
#[should_panic(expected = "Can only free a generation if it's not already freed")]
fn test_double_free() {
let mut value = Generation::new();
let index = value.allocate(0);
value.free(index);
value.free(index);
}
#[test]
#[should_panic(expected = "Can not free a generation with incorrect generation_index")]
fn test_free_wrong_index() {
let mut value = Generation::new();
let index = value.allocate(0);
value.free(index);
value.allocate(0);
value.free(index);
}
}