ixa/entity/index/
mod.rs

1//! Index types for property-value lookups.
2
3use std::cell::{Ref, RefCell};
4
5use crate::entity::{Entity, EntityId, HashValueType};
6use crate::hashing::IndexSet;
7use crate::prelude::Property;
8
9mod full_index;
10mod value_count_index;
11
12pub use full_index::*;
13pub use value_count_index::*;
14
15#[derive(Debug)]
16pub enum IndexSetResult<'a, E: Entity> {
17    /// The index type cannot satisfy the query.
18    Unsupported,
19    /// The set is empty.
20    Empty,
21    /// A reference to the index set.
22    Set(Ref<'a, IndexSet<EntityId<E>>>),
23}
24
25#[derive(PartialEq, Eq, Debug)]
26pub enum IndexCountResult {
27    /// The index type cannot satisfy the query.
28    Unsupported,
29    /// The count of entities.
30    Count(usize),
31}
32
33#[derive(Debug, Copy, Clone, PartialEq, Eq)]
34pub enum PropertyIndexType {
35    Unindexed,
36    FullIndex,
37    ValueCountIndex,
38}
39
40pub enum PropertyIndex<E: Entity, P: Property<E>> {
41    Unindexed,
42    FullIndex(RefCell<FullIndex<E, P>>),
43    ValueCountIndex(RefCell<ValueCountIndex<E, P>>),
44}
45
46impl<E: Entity, P: Property<E>> PropertyIndex<E, P> {
47    pub fn index_type(&self) -> PropertyIndexType {
48        match self {
49            Self::Unindexed => PropertyIndexType::Unindexed,
50            Self::FullIndex(_) => PropertyIndexType::FullIndex,
51            Self::ValueCountIndex(_) => PropertyIndexType::ValueCountIndex,
52        }
53    }
54
55    pub fn add_entity_with_hash(&self, hash: HashValueType, entity_id: EntityId<E>) {
56        match self {
57            Self::Unindexed => {}
58            Self::FullIndex(index) => index.borrow_mut().add_entity_with_hash(hash, entity_id),
59            Self::ValueCountIndex(index) => {
60                index.borrow_mut().add_entity_with_hash(hash, entity_id);
61            }
62        }
63    }
64
65    pub fn remove_entity_with_hash(&self, hash: HashValueType, entity_id: EntityId<E>) {
66        match self {
67            Self::Unindexed => {}
68            Self::FullIndex(index) => index.borrow_mut().remove_entity_with_hash(hash, entity_id),
69            Self::ValueCountIndex(index) => {
70                index.borrow_mut().remove_entity_with_hash(hash, entity_id);
71            }
72        }
73    }
74
75    pub fn get_index_set_with_hash(
76        &self,
77        hash: HashValueType,
78    ) -> Option<Ref<IndexSet<EntityId<E>>>> {
79        match self {
80            Self::Unindexed => None,
81            Self::FullIndex(index) => {
82                let index = index.borrow();
83                Ref::filter_map(index, |idx| idx.get_with_hash(hash)).ok()
84            }
85            Self::ValueCountIndex(_) => None,
86        }
87    }
88
89    pub fn get_index_set_with_hash_result(&self, hash: HashValueType) -> IndexSetResult<'_, E> {
90        match self {
91            Self::Unindexed => IndexSetResult::<'_, E>::Unsupported,
92            Self::FullIndex(index) => {
93                let index = index.borrow();
94                match Ref::filter_map(index, |idx| idx.get_with_hash(hash)) {
95                    Ok(set) => IndexSetResult::Set(set),
96                    Err(_) => IndexSetResult::Empty,
97                }
98            }
99            Self::ValueCountIndex(_) => IndexSetResult::<'_, E>::Unsupported,
100        }
101    }
102
103    pub fn get_index_count_with_hash_result(&self, hash: HashValueType) -> IndexCountResult {
104        match self {
105            Self::Unindexed => IndexCountResult::Unsupported,
106            Self::FullIndex(index) => {
107                let index = index.borrow();
108                let count = index.get_with_hash(hash).map_or(0, |set| set.len());
109                IndexCountResult::Count(count)
110            }
111            Self::ValueCountIndex(index) => {
112                let index = index.borrow();
113                IndexCountResult::Count(index.get_with_hash(hash).unwrap_or(0))
114            }
115        }
116    }
117
118    pub fn remove_entity(&self, value: &P::CanonicalValue, entity_id: EntityId<E>) {
119        match self {
120            Self::Unindexed => {}
121            Self::FullIndex(index) => index.borrow_mut().remove_entity(value, entity_id),
122            Self::ValueCountIndex(index) => index.borrow_mut().remove_entity(value, entity_id),
123        }
124    }
125
126    pub fn add_entity(&self, value: &P::CanonicalValue, entity_id: EntityId<E>) {
127        match self {
128            Self::Unindexed => {}
129            Self::FullIndex(index) => {
130                index.borrow_mut().add_entity(value, entity_id);
131            }
132            Self::ValueCountIndex(index) => {
133                index.borrow_mut().add_entity(value, entity_id);
134            }
135        }
136    }
137
138    /// Returns `None` if there is no index.
139    pub fn max_indexed(&self) -> Option<usize> {
140        match self {
141            Self::Unindexed => None,
142            Self::FullIndex(index) => Some(index.borrow().max_indexed),
143            Self::ValueCountIndex(index) => Some(index.borrow().max_indexed),
144        }
145    }
146
147    pub fn set_max_indexed(&self, max_indexed: usize) {
148        match self {
149            Self::Unindexed => {}
150            Self::FullIndex(index) => index.borrow_mut().max_indexed = max_indexed,
151            Self::ValueCountIndex(index) => index.borrow_mut().max_indexed = max_indexed,
152        }
153    }
154}