1use fnv::FnvHashMap;
4use vec_map::VecMap;
5
6use std::collections::HashMap;
7use std::marker::PhantomData;
8use std::ops::{Index, IndexMut};
9
10use self::InnerComponentList::{Cold, Hot};
11use crate::entity::{BuildData, EditData, IndexedEntity, ModifyData};
12
13pub trait Component: 'static {}
16impl<T: 'static> Component for T {}
17
18pub trait ComponentManager: 'static {
23 fn build_manager() -> Self;
24
25 #[doc(hidden)]
26 fn __wipe_all(&mut self);
27
28 #[doc(hidden)]
29 fn __please_use_the_derive_attribute();
30}
31
32#[derive(Debug)]
33pub struct ComponentList<C, T>
34where
35 C: ComponentManager,
36 T: Component,
37{
38 pub(crate) inner: InnerComponentList<T>,
39 _marker: PhantomData<C>,
40}
41
42#[derive(Debug)]
43pub(crate) enum InnerComponentList<T>
44where
45 T: Component,
46{
47 Hot(VecMap<T>),
48 Cold(FnvHashMap<usize, T>),
49}
50
51impl<C, T> ComponentList<C, T>
52where
53 C: ComponentManager,
54 T: Component,
55{
56 pub fn hot() -> Self {
57 ComponentList {
58 inner: Hot(VecMap::new()),
59 _marker: PhantomData,
60 }
61 }
62
63 pub fn cold() -> Self {
64 ComponentList {
65 inner: Cold(HashMap::with_hasher(Default::default())),
66 _marker: PhantomData,
67 }
68 }
69
70 pub fn add(&mut self, entity: BuildData<C>, component: T) -> Option<T> {
71 self.inner.insert(entity.0.index(), component)
72 }
73
74 pub fn remove(&mut self, entity: ModifyData<C>) -> Option<T> {
75 self.inner.remove(entity.0.index())
76 }
77
78 pub fn set<E>(&mut self, entity: E, component: T) -> Option<T>
79 where
80 E: EditData<C>,
81 {
82 let result = self.inner.insert(entity.entity().index(), component);
83 if result.is_none() && !E::can_insert_components() {
84 panic!("ComponentList::set was used to insert a new component when modification of activated components was not allowed");
85 }
86 result
87 }
88
89 pub fn get<E>(&self, entity: E) -> Option<T>
90 where
91 E: EditData<C>,
92 T: Clone,
93 {
94 self.inner.get(entity.entity().index()).cloned()
95 }
96
97 pub fn has<E>(&self, entity: E) -> bool
98 where
99 E: EditData<C>,
100 {
101 self.inner.contains_key(entity.entity().index())
102 }
103
104 pub fn borrow<E>(&mut self, entity: E) -> Option<&mut T>
105 where
106 E: EditData<C>,
107 {
108 self.inner.get_mut(entity.entity().index())
109 }
110
111 #[doc(hidden)]
112 pub fn __clear(&mut self, entity: &IndexedEntity<C>) {
113 self.inner.remove(entity.index());
114 }
115
116 #[doc(hidden)]
117 pub fn __wipe(&mut self) {
118 self.inner.clear();
119 }
120}
121
122impl<C, T, E> Index<E> for ComponentList<C, T>
123where
124 C: ComponentManager,
125 T: Component,
126 E: EditData<C>,
127{
128 type Output = T;
129 fn index(&self, entity: E) -> &T {
130 self.inner.index(entity.entity().index())
131 }
132}
133
134impl<C, T, E> IndexMut<E> for ComponentList<C, T>
135where
136 C: ComponentManager,
137 T: Component,
138 E: EditData<C>,
139{
140 fn index_mut(&mut self, entity: E) -> &mut T {
141 self.inner.index_mut(entity.entity().index())
142 }
143}
144
145impl<T> InnerComponentList<T>
146where
147 T: Component,
148{
149 pub(crate) fn insert(&mut self, index: usize, component: T) -> Option<T> {
150 match *self {
151 Hot(ref mut map) => map.insert(index, component),
152 Cold(ref mut map) => map.insert(index, component),
153 }
154 }
155
156 pub(crate) fn remove(&mut self, index: usize) -> Option<T> {
157 match *self {
158 Hot(ref mut map) => map.remove(index),
159 Cold(ref mut map) => map.remove(&index),
160 }
161 }
162
163 pub(crate) fn contains_key(&self, index: usize) -> bool {
164 match *self {
165 Hot(ref map) => map.contains_key(index),
166 Cold(ref map) => map.contains_key(&index),
167 }
168 }
169
170 pub(crate) fn index(&self, index: usize) -> &T {
171 self.get(index)
172 .unwrap_or_else(|| panic!("Entity at index {} does not have this component attached"))
173 }
174
175 pub(crate) fn index_mut(&mut self, index: usize) -> &mut T {
176 self.get_mut(index)
177 .unwrap_or_else(|| panic!("Entity at index {} does not have this component attached"))
178 }
179
180 pub(crate) fn get(&self, index: usize) -> Option<&T> {
181 match *self {
182 Hot(ref map) => map.get(index),
183 Cold(ref map) => map.get(&index),
184 }
185 }
186
187 pub(crate) fn get_mut(&mut self, index: usize) -> Option<&mut T> {
188 match *self {
189 Hot(ref mut map) => map.get_mut(index),
190 Cold(ref mut map) => map.get_mut(&index),
191 }
192 }
193
194 pub(crate) fn clear(&mut self) {
195 match *self {
196 Hot(ref mut map) => map.clear(),
197 Cold(ref mut map) => map.clear(),
198 }
199 }
200}