Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_ecs/src/entity/hash_set.rs
6849 views
1
//! Contains the [`EntityHashSet`] type, a [`HashSet`] pre-configured to use [`EntityHash`] hashing.
2
//!
3
//! This module is a lightweight wrapper around Bevy's [`HashSet`] that is more performant for [`Entity`] keys.
4
5
use core::{
6
fmt::{self, Debug, Formatter},
7
iter::FusedIterator,
8
marker::PhantomData,
9
ops::{
10
BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Deref, DerefMut, Sub,
11
SubAssign,
12
},
13
};
14
15
use bevy_platform::collections::hash_set::{self, HashSet};
16
#[cfg(feature = "bevy_reflect")]
17
use bevy_reflect::Reflect;
18
19
use super::{Entity, EntityHash, EntitySet, EntitySetIterator, FromEntitySetIterator};
20
21
/// A [`HashSet`] pre-configured to use [`EntityHash`] hashing.
22
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
23
#[cfg_attr(feature = "serialize", derive(serde::Deserialize, serde::Serialize))]
24
#[derive(Debug, Clone, Default, PartialEq, Eq)]
25
pub struct EntityHashSet(pub(crate) HashSet<Entity, EntityHash>);
26
27
impl EntityHashSet {
28
/// Creates an empty `EntityHashSet`.
29
///
30
/// Equivalent to [`HashSet::with_hasher(EntityHash)`].
31
///
32
/// [`HashSet::with_hasher(EntityHash)`]: HashSet::with_hasher
33
pub const fn new() -> Self {
34
Self(HashSet::with_hasher(EntityHash))
35
}
36
37
/// Creates an empty `EntityHashSet` with the specified capacity.
38
///
39
/// Equivalent to [`HashSet::with_capacity_and_hasher(n, EntityHash)`].
40
///
41
/// [`HashSet::with_capacity_and_hasher(n, EntityHash)`]: HashSet::with_capacity_and_hasher
42
pub fn with_capacity(n: usize) -> Self {
43
Self(HashSet::with_capacity_and_hasher(n, EntityHash))
44
}
45
46
/// Returns the number of elements in the set.
47
pub fn len(&self) -> usize {
48
self.0.len()
49
}
50
51
/// Returns `true` if the set contains no elements.
52
pub fn is_empty(&self) -> bool {
53
self.0.is_empty()
54
}
55
56
/// Returns the inner [`HashSet`].
57
pub fn into_inner(self) -> HashSet<Entity, EntityHash> {
58
self.0
59
}
60
61
/// Clears the set, returning all elements in an iterator.
62
///
63
/// Equivalent to [`HashSet::drain`].
64
pub fn drain(&mut self) -> Drain<'_> {
65
Drain(self.0.drain(), PhantomData)
66
}
67
68
/// An iterator visiting all elements in arbitrary order.
69
/// The iterator element type is `&'a Entity`.
70
///
71
/// Equivalent to [`HashSet::iter`].
72
pub fn iter(&self) -> Iter<'_> {
73
Iter(self.0.iter(), PhantomData)
74
}
75
76
/// Drains elements which are true under the given predicate,
77
/// and returns an iterator over the removed items.
78
///
79
/// Equivalent to [`HashSet::extract_if`].
80
pub fn extract_if<F: FnMut(&Entity) -> bool>(&mut self, f: F) -> ExtractIf<'_, F> {
81
ExtractIf(self.0.extract_if(f), PhantomData)
82
}
83
}
84
85
impl Deref for EntityHashSet {
86
type Target = HashSet<Entity, EntityHash>;
87
88
fn deref(&self) -> &Self::Target {
89
&self.0
90
}
91
}
92
93
impl DerefMut for EntityHashSet {
94
fn deref_mut(&mut self) -> &mut Self::Target {
95
&mut self.0
96
}
97
}
98
99
impl<'a> IntoIterator for &'a EntityHashSet {
100
type Item = &'a Entity;
101
102
type IntoIter = Iter<'a>;
103
104
fn into_iter(self) -> Self::IntoIter {
105
Iter((&self.0).into_iter(), PhantomData)
106
}
107
}
108
109
impl IntoIterator for EntityHashSet {
110
type Item = Entity;
111
112
type IntoIter = IntoIter;
113
114
fn into_iter(self) -> Self::IntoIter {
115
IntoIter(self.0.into_iter(), PhantomData)
116
}
117
}
118
119
impl BitAnd for &EntityHashSet {
120
type Output = EntityHashSet;
121
122
fn bitand(self, rhs: Self) -> Self::Output {
123
EntityHashSet(self.0.bitand(&rhs.0))
124
}
125
}
126
127
impl BitAndAssign<&EntityHashSet> for EntityHashSet {
128
fn bitand_assign(&mut self, rhs: &Self) {
129
self.0.bitand_assign(&rhs.0);
130
}
131
}
132
133
impl BitOr for &EntityHashSet {
134
type Output = EntityHashSet;
135
136
fn bitor(self, rhs: Self) -> Self::Output {
137
EntityHashSet(self.0.bitor(&rhs.0))
138
}
139
}
140
141
impl BitOrAssign<&EntityHashSet> for EntityHashSet {
142
fn bitor_assign(&mut self, rhs: &Self) {
143
self.0.bitor_assign(&rhs.0);
144
}
145
}
146
147
impl BitXor for &EntityHashSet {
148
type Output = EntityHashSet;
149
150
fn bitxor(self, rhs: Self) -> Self::Output {
151
EntityHashSet(self.0.bitxor(&rhs.0))
152
}
153
}
154
155
impl BitXorAssign<&EntityHashSet> for EntityHashSet {
156
fn bitxor_assign(&mut self, rhs: &Self) {
157
self.0.bitxor_assign(&rhs.0);
158
}
159
}
160
161
impl Sub for &EntityHashSet {
162
type Output = EntityHashSet;
163
164
fn sub(self, rhs: Self) -> Self::Output {
165
EntityHashSet(self.0.sub(&rhs.0))
166
}
167
}
168
169
impl SubAssign<&EntityHashSet> for EntityHashSet {
170
fn sub_assign(&mut self, rhs: &Self) {
171
self.0.sub_assign(&rhs.0);
172
}
173
}
174
175
impl<'a> Extend<&'a Entity> for EntityHashSet {
176
fn extend<T: IntoIterator<Item = &'a Entity>>(&mut self, iter: T) {
177
self.0.extend(iter);
178
}
179
}
180
181
impl Extend<Entity> for EntityHashSet {
182
fn extend<T: IntoIterator<Item = Entity>>(&mut self, iter: T) {
183
self.0.extend(iter);
184
}
185
}
186
187
impl<const N: usize> From<[Entity; N]> for EntityHashSet {
188
fn from(value: [Entity; N]) -> Self {
189
Self(HashSet::from_iter(value))
190
}
191
}
192
193
impl FromIterator<Entity> for EntityHashSet {
194
fn from_iter<I: IntoIterator<Item = Entity>>(iterable: I) -> Self {
195
Self(HashSet::from_iter(iterable))
196
}
197
}
198
199
impl FromEntitySetIterator<Entity> for EntityHashSet {
200
fn from_entity_set_iter<I: EntitySet<Item = Entity>>(set_iter: I) -> Self {
201
let iter = set_iter.into_iter();
202
let set = EntityHashSet::with_capacity(iter.size_hint().0);
203
iter.fold(set, |mut set, e| {
204
// SAFETY: Every element in self is unique.
205
unsafe {
206
set.insert_unique_unchecked(e);
207
}
208
set
209
})
210
}
211
}
212
213
/// An iterator over the items of an [`EntityHashSet`].
214
///
215
/// This struct is created by the [`iter`] method on [`EntityHashSet`]. See its documentation for more.
216
///
217
/// [`iter`]: EntityHashSet::iter
218
pub struct Iter<'a, S = EntityHash>(hash_set::Iter<'a, Entity>, PhantomData<S>);
219
220
impl<'a> Iter<'a> {
221
/// Returns the inner [`Iter`](hash_set::Iter).
222
pub fn into_inner(self) -> hash_set::Iter<'a, Entity> {
223
self.0
224
}
225
}
226
227
impl<'a> Deref for Iter<'a> {
228
type Target = hash_set::Iter<'a, Entity>;
229
230
fn deref(&self) -> &Self::Target {
231
&self.0
232
}
233
}
234
235
impl<'a> Iterator for Iter<'a> {
236
type Item = &'a Entity;
237
238
fn next(&mut self) -> Option<Self::Item> {
239
self.0.next()
240
}
241
}
242
243
impl ExactSizeIterator for Iter<'_> {}
244
245
impl FusedIterator for Iter<'_> {}
246
247
impl Clone for Iter<'_> {
248
fn clone(&self) -> Self {
249
Self(self.0.clone(), PhantomData)
250
}
251
}
252
253
impl Debug for Iter<'_> {
254
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
255
f.debug_tuple("Iter").field(&self.0).field(&self.1).finish()
256
}
257
}
258
259
impl Default for Iter<'_> {
260
fn default() -> Self {
261
Self(Default::default(), PhantomData)
262
}
263
}
264
265
// SAFETY: Iter stems from a correctly behaving `HashSet<Entity, EntityHash>`.
266
unsafe impl EntitySetIterator for Iter<'_> {}
267
268
/// Owning iterator over the items of an [`EntityHashSet`].
269
///
270
/// This struct is created by the [`into_iter`] method on [`EntityHashSet`] (provided by the [`IntoIterator`] trait). See its documentation for more.
271
///
272
/// [`into_iter`]: EntityHashSet::into_iter
273
pub struct IntoIter<S = EntityHash>(hash_set::IntoIter<Entity>, PhantomData<S>);
274
275
impl IntoIter {
276
/// Returns the inner [`IntoIter`](hash_set::IntoIter).
277
pub fn into_inner(self) -> hash_set::IntoIter<Entity> {
278
self.0
279
}
280
}
281
282
impl Deref for IntoIter {
283
type Target = hash_set::IntoIter<Entity>;
284
285
fn deref(&self) -> &Self::Target {
286
&self.0
287
}
288
}
289
290
impl Iterator for IntoIter {
291
type Item = Entity;
292
293
fn next(&mut self) -> Option<Self::Item> {
294
self.0.next()
295
}
296
}
297
298
impl ExactSizeIterator for IntoIter {}
299
300
impl FusedIterator for IntoIter {}
301
302
impl Debug for IntoIter {
303
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304
f.debug_tuple("IntoIter")
305
.field(&self.0)
306
.field(&self.1)
307
.finish()
308
}
309
}
310
311
impl Default for IntoIter {
312
fn default() -> Self {
313
Self(Default::default(), PhantomData)
314
}
315
}
316
317
// SAFETY: IntoIter stems from a correctly behaving `HashSet<Entity, EntityHash>`.
318
unsafe impl EntitySetIterator for IntoIter {}
319
320
/// A draining iterator over the items of an [`EntityHashSet`].
321
///
322
/// This struct is created by the [`drain`] method on [`EntityHashSet`]. See its documentation for more.
323
///
324
/// [`drain`]: EntityHashSet::drain
325
pub struct Drain<'a, S = EntityHash>(hash_set::Drain<'a, Entity>, PhantomData<S>);
326
327
impl<'a> Drain<'a> {
328
/// Returns the inner [`Drain`](hash_set::Drain).
329
pub fn into_inner(self) -> hash_set::Drain<'a, Entity> {
330
self.0
331
}
332
}
333
334
impl<'a> Deref for Drain<'a> {
335
type Target = hash_set::Drain<'a, Entity>;
336
337
fn deref(&self) -> &Self::Target {
338
&self.0
339
}
340
}
341
342
impl<'a> Iterator for Drain<'a> {
343
type Item = Entity;
344
345
fn next(&mut self) -> Option<Self::Item> {
346
self.0.next()
347
}
348
}
349
350
impl ExactSizeIterator for Drain<'_> {}
351
352
impl FusedIterator for Drain<'_> {}
353
354
impl Debug for Drain<'_> {
355
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
356
f.debug_tuple("Drain")
357
.field(&self.0)
358
.field(&self.1)
359
.finish()
360
}
361
}
362
363
// SAFETY: Drain stems from a correctly behaving `HashSet<Entity, EntityHash>`.
364
unsafe impl EntitySetIterator for Drain<'_> {}
365
366
/// A draining iterator over entries of a [`EntityHashSet`] which don't satisfy the predicate `f`.
367
///
368
/// This struct is created by the [`extract_if`] method on [`EntityHashSet`]. See its documentation for more.
369
///
370
/// [`extract_if`]: EntityHashSet::extract_if
371
pub struct ExtractIf<'a, F: FnMut(&Entity) -> bool, S = EntityHash>(
372
hash_set::ExtractIf<'a, Entity, F>,
373
PhantomData<S>,
374
);
375
376
impl<'a, F: FnMut(&Entity) -> bool> ExtractIf<'a, F> {
377
/// Returns the inner [`ExtractIf`](hash_set::ExtractIf).
378
pub fn into_inner(self) -> hash_set::ExtractIf<'a, Entity, F> {
379
self.0
380
}
381
}
382
383
impl<'a, F: FnMut(&Entity) -> bool> Deref for ExtractIf<'a, F> {
384
type Target = hash_set::ExtractIf<'a, Entity, F>;
385
386
fn deref(&self) -> &Self::Target {
387
&self.0
388
}
389
}
390
391
impl<'a, F: FnMut(&Entity) -> bool> Iterator for ExtractIf<'a, F> {
392
type Item = Entity;
393
394
fn next(&mut self) -> Option<Self::Item> {
395
self.0.next()
396
}
397
}
398
399
impl<F: FnMut(&Entity) -> bool> FusedIterator for ExtractIf<'_, F> {}
400
401
impl<F: FnMut(&Entity) -> bool> Debug for ExtractIf<'_, F> {
402
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
403
f.debug_tuple("ExtractIf").finish()
404
}
405
}
406
407
// SAFETY: ExtractIf stems from a correctly behaving `HashSet<Entity, EntityHash>`.
408
unsafe impl<F: FnMut(&Entity) -> bool> EntitySetIterator for ExtractIf<'_, F> {}
409
410
// SAFETY: Difference stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
411
unsafe impl EntitySetIterator for hash_set::Difference<'_, Entity, EntityHash> {}
412
413
// SAFETY: Intersection stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
414
unsafe impl EntitySetIterator for hash_set::Intersection<'_, Entity, EntityHash> {}
415
416
// SAFETY: SymmetricDifference stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
417
unsafe impl EntitySetIterator for hash_set::SymmetricDifference<'_, Entity, EntityHash> {}
418
419
// SAFETY: Union stems from two correctly behaving `HashSet<Entity, EntityHash>`s.
420
unsafe impl EntitySetIterator for hash_set::Union<'_, Entity, EntityHash> {}
421
422