use std::cell::RefCell;
use std::vec::Vec;
use super::entity::{Entity, EntityId};
use super::property::{Property, PropertyInitializationKind};
use crate::entity::index::{PropertyIndex, PropertyIndexType};
use crate::entity::property_value_store::PropertyValueStore;
use crate::entity::value_change_counter::ValueChangeCounter;
pub(crate) type RawPropertyValueVec<P> = Vec<P>;
pub struct PropertyValueStoreCore<E: Entity, P: Property<E>> {
pub(super) data: RawPropertyValueVec<P>,
pub(crate) index: PropertyIndex<E, P>,
pub(crate) value_change_counters: Vec<RefCell<Box<dyn ValueChangeCounter<E, P>>>>,
}
impl<E: Entity, P: Property<E>> Default for PropertyValueStoreCore<E, P> {
fn default() -> Self {
Self {
data: RawPropertyValueVec::default(),
index: PropertyIndex::Unindexed,
value_change_counters: Vec::new(),
}
}
}
impl<E: Entity, P: Property<E>> PropertyValueStoreCore<E, P> {
pub(crate) fn new() -> Self {
Self::default()
}
pub(crate) fn new_boxed() -> Box<dyn PropertyValueStore<E>> {
Box::new(Self::new())
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
data: RawPropertyValueVec::with_capacity(capacity),
index: PropertyIndex::Unindexed,
value_change_counters: Vec::new(),
}
}
pub(crate) fn index_type(&self) -> PropertyIndexType {
self.index.index_type()
}
pub(crate) fn add_value_change_counter(
&mut self,
counter: Box<dyn ValueChangeCounter<E, P>>,
) -> usize {
let counter_id = self.value_change_counters.len();
self.value_change_counters.push(RefCell::new(counter));
counter_id
}
pub fn reserve(&mut self, additional: usize) {
self.data.reserve(additional);
}
pub fn get(&self, entity_id: EntityId<E>) -> P {
debug_assert!(
!P::is_derived(),
"Tried to get a derived property value from property value store."
);
self.data.get(entity_id.0).copied().unwrap_or_else(
P::default_const,
)
}
pub fn set(&mut self, entity_id: EntityId<E>, value: P) {
debug_assert!(
!P::is_derived(),
"Tried to set a derived property value in property value store."
);
let index = entity_id.0;
let len = self.data.len();
if index < len {
self.data[index] = value;
return;
}
if P::initialization_kind() == PropertyInitializationKind::Constant {
let default_value = P::default_const();
if value == default_value {
return;
}
self.data.reserve(index + 1 - len);
self.data.resize(index, default_value);
self.data.push(value);
} else if index == len {
self.data.push(value);
} else {
unreachable!("Property storage state is inconsistent: one or more properties do not have values.");
}
}
pub fn replace(&mut self, entity_id: EntityId<E>, value: P) -> P {
debug_assert!(
!P::is_derived(),
"Tried to replace a derived property value in property value store."
);
let index = entity_id.0;
let len = self.data.len();
if index < len {
return std::mem::replace(&mut self.data[index], value);
}
if P::initialization_kind() == PropertyInitializationKind::Constant {
let default_value = P::default_const();
if value == default_value {
return default_value;
}
self.data.reserve(index + 1 - len);
self.data.resize(index, default_value);
self.data.push(value);
default_value
} else {
unreachable!("Property storage state is inconsistent: one or more properties do not have values.");
}
}
}