stable_id/
sparse_entities.rs1use std::{
2 hash::Hash,
3 ops::{Index, IndexMut},
4};
5
6use stable_id_traits::Successor;
7
8use super::SparseEntities;
9
10impl<IndexT, DataT> SparseEntities<IndexT, DataT>
11where
12 IndexT: Successor + Clone + Copy + Hash + Eq + Default,
13{
14 pub fn len(&self) -> usize {
15 self.data.len()
16 }
17
18 pub fn is_empty(&self) -> bool {
19 self.data.is_empty()
20 }
21
22 pub fn get(&self, index: IndexT) -> Option<&DataT> {
23 self.data.get(&index)
24 }
25
26 pub fn get_mut(&mut self, index: IndexT) -> Option<&mut DataT> {
27 self.data.get_mut(&index)
28 }
29
30 pub fn remove(&mut self, index: IndexT) -> DataT {
32 self.data.remove(&index).expect("id is not value")
33 }
34
35 pub fn alloc(&mut self, data: DataT) -> IndexT {
36 let next_id = self.seq.next_value();
37 self.data.insert(next_id, data);
38
39 next_id
40 }
41
42 pub fn iter(&self) -> impl Iterator<Item = (IndexT, &DataT)> {
43 self.data
44 .iter()
45 .map(|(virtual_id, data)| (*virtual_id, data))
46 }
47
48 pub fn iter_mut(&mut self) -> impl Iterator<Item = (IndexT, &mut DataT)> {
49 self.data
50 .iter_mut()
51 .map(|(virtual_id, data)| (*virtual_id, data))
52 }
53}
54
55impl<IndexT, DataT> IntoIterator for SparseEntities<IndexT, DataT>
56where
57 IndexT: Successor + Clone + Copy + Default + Hash + Eq,
58{
59 type Item = (IndexT, DataT);
60
61 type IntoIter = std::collections::hash_map::IntoIter<IndexT, DataT>;
62
63 fn into_iter(self) -> Self::IntoIter {
64 self.data.into_iter()
65 }
66}
67
68impl<IndexT, DataT> Default for SparseEntities<IndexT, DataT>
69where
70 IndexT: Default,
71{
72 fn default() -> Self {
73 Self {
74 data: Default::default(),
75 seq: Default::default(),
76 }
77 }
78}
79
80impl<IndexT, DataT> Index<IndexT> for SparseEntities<IndexT, DataT>
81where
82 IndexT: Successor + Clone + Copy + Hash + Eq + Default,
83{
84 type Output = DataT;
85
86 fn index(&self, index: IndexT) -> &Self::Output {
87 self.get(index).expect("element not exist")
88 }
89}
90
91impl<IndexT, DataT> IndexMut<IndexT> for SparseEntities<IndexT, DataT>
92where
93 IndexT: Successor + Clone + Copy + Hash + Eq + Default,
94{
95 fn index_mut(&mut self, index: IndexT) -> &mut Self::Output {
96 self.get_mut(index).expect("element not exist")
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use std::collections::HashMap;
103
104 use crate::SparseEntities;
105
106 #[test]
107 fn access_out_of_bound() {
108 let mut entities = SparseEntities::default();
109 entities.alloc(1232);
110 assert_eq!(entities.get(312u16), None);
111 }
112
113 #[test]
114 #[should_panic(expected = "element not exist")]
115 fn access_out_of_bound_mut() {
116 let mut entities = SparseEntities::default();
117 entities.alloc(1232);
118 entities[312u16] = 3333;
119 }
120
121 #[test]
122 fn normal() {
123 let mut entities = SparseEntities::default();
124
125 fn check_all(entities: &SparseEntities<usize, &str>) {
126 entities
127 .iter()
128 .for_each(|(id, data)| assert_eq!(entities[id], *data));
129 }
130
131 vec!["1", "2", "3", "4", "5"]
132 .into_iter()
133 .fold(HashMap::new(), |mut acc, data| {
134 acc.insert(entities.alloc(data), data);
135 acc
136 })
137 .into_iter()
138 .for_each(|(id, data)| assert_eq!(entities[id], data));
139
140 entities.remove(1);
141 check_all(&entities);
142
143 entities.remove(4);
144 check_all(&entities);
145
146 entities.remove(3);
147 check_all(&entities);
148
149 entities.remove(2);
150 assert_eq!(entities.len(), 1);
151 check_all(&entities);
152
153 entities.remove(0);
154 assert!(entities.is_empty());
155 check_all(&entities);
156 }
157}