#![allow(unused)]
use std::any::Any;
use log::{error, trace};
use crate::entity::events::{
PartialPropertyChangeEvent, PartialPropertyChangeEventBox, PartialPropertyChangeEventCore,
PropertyChangeEvent,
};
use crate::entity::index::{
FullIndex, IndexCountResult, IndexSetResult, PropertyIndex, PropertyIndexType, ValueCountIndex,
};
use crate::entity::property::Property;
use crate::entity::property_value_store_core::PropertyValueStoreCore;
use crate::entity::{Entity, EntityId, HashValueType};
use crate::hashing::IndexSet;
use crate::{Context, ContextEntitiesExt};
pub(crate) trait PropertyValueStore<E: Entity>: Any {
fn as_any_mut(&mut self) -> &mut dyn Any;
fn as_any(&self) -> &dyn Any;
fn create_partial_property_change(
&self,
entity_id: EntityId<E>,
context: &Context,
) -> PartialPropertyChangeEventBox;
fn should_create_partial_change(&self, context: &Context) -> bool;
fn add_entity_to_index_with_hash(&mut self, hash: HashValueType, entity_id: EntityId<E>);
fn remove_entity_from_index_with_hash(&mut self, hash: HashValueType, entity_id: EntityId<E>);
fn get_index_set_with_hash(&self, hash: HashValueType) -> Option<&IndexSet<EntityId<E>>>;
fn get_index_set_with_hash_result(&self, hash: HashValueType) -> IndexSetResult<'_, E>;
fn get_index_count_with_hash_result(&self, hash: HashValueType) -> IndexCountResult;
fn index_type(&self) -> PropertyIndexType;
fn set_indexed(&mut self, index_type: PropertyIndexType);
fn index_unindexed_entities(&mut self, context: &Context);
}
impl<E: Entity, P: Property<E>> PropertyValueStore<E> for PropertyValueStoreCore<E, P> {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
fn as_any(&self) -> &dyn Any {
self
}
fn create_partial_property_change(
&self,
entity_id: EntityId<E>,
context: &Context,
) -> PartialPropertyChangeEventBox {
let previous_value = if P::is_derived() {
P::compute_derived(context, entity_id)
} else {
self.get(entity_id)
};
smallbox::smallbox!(PartialPropertyChangeEventCore::<E, P>::new(
entity_id,
previous_value,
))
}
fn should_create_partial_change(&self, context: &Context) -> bool {
context.has_event_handlers::<PropertyChangeEvent<E, P>>()
|| !self.value_change_counters.is_empty()
|| self.index.index_type() != PropertyIndexType::Unindexed
}
fn add_entity_to_index_with_hash(&mut self, hash: HashValueType, entity_id: EntityId<E>) {
if self.index.index_type() != PropertyIndexType::Unindexed {
self.index.add_entity_with_hash(hash, entity_id);
} else {
error!("attempted to add an entity to an index for an unindexed property");
}
}
fn remove_entity_from_index_with_hash(&mut self, hash: HashValueType, entity_id: EntityId<E>) {
if self.index.index_type() != PropertyIndexType::Unindexed {
self.index.remove_entity_with_hash(hash, entity_id);
} else {
error!("attempted to remove an entity from an index for an unindexed property");
}
}
fn get_index_set_with_hash(&self, hash: HashValueType) -> Option<&IndexSet<EntityId<E>>> {
self.index.get_index_set_with_hash(hash)
}
fn get_index_set_with_hash_result(&self, hash: HashValueType) -> IndexSetResult<'_, E> {
self.index.get_index_set_with_hash_result(hash)
}
fn get_index_count_with_hash_result(&self, hash: HashValueType) -> IndexCountResult {
self.index.get_index_count_with_hash_result(hash)
}
fn index_type(&self) -> PropertyIndexType {
self.index_type()
}
fn set_indexed(&mut self, index_type: PropertyIndexType) {
match index_type {
PropertyIndexType::Unindexed => {
self.index = PropertyIndex::Unindexed;
}
PropertyIndexType::FullIndex => {
if self.index.index_type() != PropertyIndexType::FullIndex {
self.index = PropertyIndex::FullIndex(FullIndex::new());
}
}
PropertyIndexType::ValueCountIndex => {
if self.index.index_type() != PropertyIndexType::ValueCountIndex {
self.index = PropertyIndex::ValueCountIndex(ValueCountIndex::<E, P>::new());
}
}
}
}
fn index_unindexed_entities(&mut self, context: &Context) {
let current_pop = context.get_entity_count::<E>();
let max_indexed = match self.index.max_indexed() {
None => return,
Some(max_indexed) if max_indexed >= current_pop => return,
Some(max_indexed) => max_indexed,
};
trace!(
"{}: indexing unindexed entity {}..<{}",
P::name(),
max_indexed,
current_pop
);
for id in max_indexed..current_pop {
let entity_id = EntityId::new(id);
let value = if P::is_derived() {
P::compute_derived(context, entity_id)
} else {
self.get(entity_id)
};
self.index.add_entity(&P::make_canonical(value), entity_id);
}
self.index.set_max_indexed(current_pop);
}
}