1use crate::entity::entity_set::entity_set::{EntitySet, EntitySetInner};
14use crate::entity::entity_set::source_iterator::{PopulationRangeIterator, SourceIterator};
15use crate::entity::entity_set::source_set::SourceSet;
16use crate::entity::{Entity, EntityId, PopulationIterator};
17use crate::hashing::IndexSet;
18
19enum EntitySetIteratorInner<'a, E: Entity> {
20 Source(SourceIterator<'a, E>),
21 IntersectionSources {
25 driver: SourceIterator<'a, E>,
26 filters: Vec<SourceSet<'a, E>>,
27 },
28 Intersection {
29 driver: Box<EntitySetIteratorInner<'a, E>>,
30 filters: Vec<EntitySet<'a, E>>,
31 },
32 Difference {
33 left: Box<EntitySetIteratorInner<'a, E>>,
34 right: EntitySet<'a, E>,
35 },
36 Union {
37 left: Box<EntitySetIteratorInner<'a, E>>,
38 right: UnionRightState<'a, E>,
39 },
40}
41
42enum UnionRightState<'a, E: Entity> {
43 Pending(Option<EntitySet<'a, E>>),
44 Active(Box<EntitySetIteratorInner<'a, E>>),
45}
46
47impl<'a, E: Entity> EntitySetIteratorInner<'a, E> {
48 fn empty_source() -> Self {
49 Self::Source(SourceIterator::PopulationRange(
50 PopulationRangeIterator::new(0..0),
51 ))
52 }
53
54 fn from_entity_set(set: EntitySet<'a, E>) -> Self {
55 match set.into_inner() {
56 EntitySetInner::Source(source) => {
57 if source.try_len() == Some(0) {
58 Self::empty_source()
59 } else {
60 Self::Source(source.into_iter())
61 }
62 }
63 EntitySetInner::Intersection(mut sets) => {
64 if sets.is_empty() {
65 return Self::empty_source();
66 }
67 if sets.len() == 1 {
68 return Self::from_entity_set(sets.pop().unwrap());
69 }
70
71 if sets.iter().all(EntitySet::is_source_leaf) {
72 let mut set_iter = sets.into_iter();
75
76 let first = set_iter.next().unwrap().into_source_leaf().unwrap();
77 let driver = first.into_iter();
78
79 let filters = set_iter
80 .map(|set| set.into_source_leaf().unwrap())
81 .collect();
82
83 return Self::IntersectionSources { driver, filters };
84 }
85
86 let mut set_iter = sets.into_iter();
90 let driver = Box::new(Self::from_entity_set(set_iter.next().unwrap()));
91 Self::Intersection {
92 driver,
93 filters: set_iter.collect(),
94 }
95 }
96 EntitySetInner::Difference(left, right) => Self::Difference {
97 left: Box::new(Self::from_entity_set(*left)),
98 right: *right,
99 },
100 EntitySetInner::Union(left, right) => Self::Union {
101 left: Box::new(Self::from_entity_set(*left)),
102 right: UnionRightState::Pending(Some(*right)),
103 },
104 }
105 }
106
107 fn contains(&self, entity_id: EntityId<E>) -> bool {
108 match self {
109 Self::Source(iter) => iter.contains(entity_id),
110 Self::IntersectionSources { driver, filters } => {
111 driver.contains(entity_id) && filters.iter().all(|set| set.contains(entity_id))
112 }
113 Self::Intersection { driver, filters } => {
114 driver.contains(entity_id) && filters.iter().all(|set| set.contains(entity_id))
115 }
116 Self::Difference { left, right } => {
117 left.contains(entity_id) && !right.contains(entity_id)
118 }
119 Self::Union { left, right } => left.contains(entity_id) || right.contains(entity_id),
120 }
121 }
122}
123
124impl<'a, E: Entity> UnionRightState<'a, E> {
125 fn contains(&self, entity_id: EntityId<E>) -> bool {
126 match self {
127 Self::Pending(Some(set)) => set.contains(entity_id),
128 Self::Pending(None) => false,
129 Self::Active(iter) => iter.contains(entity_id),
130 }
131 }
132}
133
134impl<'a, E: Entity> EntitySetIteratorInner<'a, E> {
135 #[inline]
136 fn next_inner(&mut self) -> Option<EntityId<E>> {
137 match self {
138 Self::Source(source) => source.next(),
139 Self::IntersectionSources { driver, filters } => driver
140 .by_ref()
141 .find(|&entity_id| filters.iter().all(|filter| filter.contains(entity_id))),
142 Self::Intersection { driver, filters } => {
143 while let Some(entity_id) = driver.next_inner() {
144 if filters.iter().all(|filter| filter.contains(entity_id)) {
145 return Some(entity_id);
146 }
147 }
148 None
149 }
150 Self::Difference { left, right } => {
151 while let Some(entity_id) = left.next_inner() {
152 if !right.contains(entity_id) {
153 return Some(entity_id);
154 }
155 }
156 None
157 }
158 Self::Union { left, right } => loop {
159 if let Some(entity_id) = left.next_inner() {
160 return Some(entity_id);
161 }
162
163 match right {
164 UnionRightState::Pending(maybe_set) => {
165 if let Some(set) = maybe_set.take() {
166 *right = UnionRightState::Active(Box::new(Self::from_entity_set(set)));
167 }
168 continue;
169 }
170 UnionRightState::Active(right_iter) => {
171 while let Some(entity_id) = right_iter.next_inner() {
172 if !left.contains(entity_id) {
173 return Some(entity_id);
174 }
175 }
176 return None;
177 }
178 }
179 },
180 }
181 }
182
183 #[inline]
184 fn size_hint_inner(&self) -> (usize, Option<usize>) {
185 match self {
186 Self::Source(source) => source.size_hint(),
187 Self::IntersectionSources { driver, .. } => {
188 let (_, upper) = driver.size_hint();
189 (0, upper)
190 }
191 Self::Intersection { driver, .. } => {
192 let (_, upper) = driver.size_hint_inner();
193 (0, upper)
194 }
195 Self::Difference { left, .. } => {
196 let (_, upper) = left.size_hint_inner();
197 (0, upper)
198 }
199 Self::Union { left, right } => {
200 let (_, left_upper) = left.size_hint_inner();
201 let right_upper = match right {
202 UnionRightState::Pending(_) => None,
203 UnionRightState::Active(right_iter) => right_iter.size_hint_inner().1,
204 };
205 let upper = match (left_upper, right_upper) {
206 (Some(a), Some(b)) => Some(a.saturating_add(b)),
207 _ => None,
208 };
209 (0, upper)
210 }
211 }
212 }
213}
214
215pub struct EntitySetIterator<'c, E: Entity> {
217 inner: EntitySetIteratorInner<'c, E>,
218}
219
220impl<'c, E: Entity> EntitySetIterator<'c, E> {
221 pub(crate) fn empty() -> EntitySetIterator<'c, E> {
222 EntitySetIterator {
223 inner: EntitySetIteratorInner::empty_source(),
224 }
225 }
226
227 pub(crate) fn from_population_iterator(iter: PopulationIterator<E>) -> Self {
228 EntitySetIterator {
229 inner: EntitySetIteratorInner::Source(SourceIterator::PopulationRange(
230 PopulationRangeIterator::from_population_iterator(iter),
231 )),
232 }
233 }
234
235 pub(crate) fn from_sources(mut sources: Vec<SourceSet<'c, E>>) -> Self {
236 if sources.is_empty() {
237 return Self::empty();
238 }
239 if sources.len() == 1 {
240 return EntitySetIterator {
241 inner: EntitySetIteratorInner::Source(sources.pop().unwrap().into_iter()),
242 };
243 }
244
245 sources.sort_unstable_by_key(SourceSet::sort_key);
248 let mut source_iter = sources.into_iter();
249 let driver = source_iter.next().unwrap().into_iter();
250 EntitySetIterator {
251 inner: EntitySetIteratorInner::IntersectionSources {
252 driver,
253 filters: source_iter.collect(),
254 },
255 }
256 }
257
258 pub(crate) fn from_index_set(set: &'c IndexSet<EntityId<E>>) -> EntitySetIterator<'c, E> {
259 EntitySetIterator {
260 inner: EntitySetIteratorInner::Source(SourceSet::IndexSet(set).into_iter()),
261 }
262 }
263
264 pub(super) fn new(set: EntitySet<'c, E>) -> Self {
265 EntitySetIterator {
266 inner: EntitySetIteratorInner::from_entity_set(set),
267 }
268 }
269}
270
271impl<'a, E: Entity> Iterator for EntitySetIterator<'a, E> {
272 type Item = EntityId<E>;
273
274 #[inline]
275 fn next(&mut self) -> Option<Self::Item> {
276 self.inner.next_inner()
277 }
278
279 #[inline]
280 fn size_hint(&self) -> (usize, Option<usize>) {
281 self.inner.size_hint_inner()
282 }
283
284 fn count(self) -> usize {
285 let EntitySetIterator { inner } = self;
286 match inner {
287 EntitySetIteratorInner::Source(source) => source.count(),
288 EntitySetIteratorInner::IntersectionSources {
289 mut driver,
290 filters,
291 } => driver
292 .by_ref()
293 .filter(|&entity_id| filters.iter().all(|filter| filter.contains(entity_id)))
294 .count(),
295 other => {
296 let mut it = EntitySetIterator { inner: other };
297 let mut n = 0usize;
298 while it.next().is_some() {
299 n += 1;
300 }
301 n
302 }
303 }
304 }
305
306 #[inline]
307 fn nth(&mut self, n: usize) -> Option<Self::Item> {
308 match &mut self.inner {
309 EntitySetIteratorInner::Source(source) => source.nth(n),
310 EntitySetIteratorInner::IntersectionSources { driver, filters } => driver
311 .by_ref()
312 .filter(|&entity_id| filters.iter().all(|filter| filter.contains(entity_id)))
313 .nth(n),
314 _ => {
315 for _ in 0..n {
316 self.next()?;
317 }
318 self.next()
319 }
320 }
321 }
322
323 fn for_each<F>(self, mut f: F)
324 where
325 F: FnMut(Self::Item),
326 {
327 let EntitySetIterator { inner } = self;
328 match inner {
329 EntitySetIteratorInner::Source(source) => source.for_each(f),
330 other => {
331 let it = EntitySetIterator { inner: other };
332 for item in it {
333 f(item);
334 }
335 }
336 }
337 }
338
339 fn fold<B, F>(self, init: B, mut f: F) -> B
340 where
341 F: FnMut(B, Self::Item) -> B,
342 {
343 let EntitySetIterator { inner } = self;
344 match inner {
345 EntitySetIteratorInner::Source(source) => source.fold(init, f),
346 other => {
347 let it = EntitySetIterator { inner: other };
348 let mut acc = init;
349 for item in it {
350 acc = f(acc, item);
351 }
352 acc
353 }
354 }
355 }
356}
357
358impl<'c, E: Entity> std::iter::FusedIterator for EntitySetIterator<'c, E> {}
359
360#[cfg(test)]
361mod tests {
362 use indexmap::IndexSet;
388
389 use crate::entity::entity_set::{EntitySet, SourceSet};
390 use crate::hashing::IndexSet as FxIndexSet;
391 use crate::prelude::*;
392 use crate::{define_derived_property, define_property, with};
393
394 define_entity!(Person);
395
396 define_property!(struct ExplicitProp(u8), Person);
400
401 define_property!(struct ConstantProp(u8), Person, default_const = ConstantProp(42));
403
404 define_derived_property!(struct DerivedProp(bool), Person, [ExplicitProp], |explicit| {
406 DerivedProp(explicit.0 % 2 == 0)
407 });
408
409 define_property!(struct ConstantProp2(u16), Person, default_const = ConstantProp2(100));
411 define_property!(struct ExplicitProp2(bool), Person);
412
413 define_property!(struct Age(u8), Person, default_const = Age(0));
414 define_property!(struct Alive(bool), Person, default_const = Alive(true));
415
416 define_derived_property!(
417 enum AgeGroupRisk {
418 NewBorn,
419 General,
420 OldAdult,
421 },
422 Person,
423 [Age],
424 [],
425 |age| {
426 if age.0 <= 1 {
427 AgeGroupRisk::NewBorn
428 } else if age.0 <= 65 {
429 AgeGroupRisk::General
430 } else {
431 AgeGroupRisk::OldAdult
432 }
433 }
434 );
435
436 fn setup_test_population(context: &mut Context, size: usize) -> Vec<EntityId<Person>> {
438 let mut people = Vec::new();
439 for i in 0..size {
440 let person = context
441 .add_entity(with!(
442 Person,
443 ExplicitProp((i % 20) as u8),
444 ExplicitProp2(i % 2 == 0)
445 ))
446 .unwrap();
447 people.push(person);
448 }
449 people
450 }
451
452 #[test]
456 fn test_explicit_non_default_not_indexed_initial_source_yes() {
457 let mut context = Context::new();
458 setup_test_population(&mut context, 100);
459
460 let results = context
461 .query_result_iterator(with!(Person, ExplicitProp(5)))
462 .collect::<Vec<_>>();
463
464 assert_eq!(results.len(), 5); for person in results {
466 assert_eq!(
467 context.get_property::<_, ExplicitProp>(person),
468 ExplicitProp(5)
469 );
470 }
471 }
472
473 #[test]
475 fn test_explicit_non_default_indexed_initial_source_yes() {
476 let mut context = Context::new();
477 context.index_property::<Person, ExplicitProp>();
478 setup_test_population(&mut context, 100);
479
480 let results = context
481 .query_result_iterator(with!(Person, ExplicitProp(7)))
482 .collect::<Vec<_>>();
483
484 assert_eq!(results.len(), 5); for person in results {
486 assert_eq!(
487 context.get_property::<_, ExplicitProp>(person),
488 ExplicitProp(7)
489 );
490 }
491 }
492
493 #[test]
495 fn test_constant_default_not_indexed_initial_source_yes() {
496 let mut context = Context::new();
497 for _ in 0..50 {
499 context
500 .add_entity(with!(Person, ExplicitProp(1), ExplicitProp2(false)))
501 .unwrap();
502 }
503
504 let results = context
505 .query_result_iterator(with!(Person, ConstantProp(42), ExplicitProp2(false)))
506 .collect::<Vec<_>>();
507
508 assert_eq!(results.len(), 50);
509 for person in results {
510 assert_eq!(
511 context.get_property::<_, ConstantProp>(person),
512 ConstantProp(42)
513 );
514 }
515 }
516
517 #[test]
519 fn test_constant_default_indexed_initial_source_yes() {
520 let mut context = Context::new();
521 context.index_property::<Person, ConstantProp>();
522
523 for _ in 0..50 {
524 context
525 .add_entity(with!(Person, ExplicitProp(1), ExplicitProp2(false)))
526 .unwrap();
527 }
528
529 let results = context
530 .query_result_iterator(with!(Person, ConstantProp(42)))
531 .collect::<Vec<_>>();
532 assert_eq!(results.len(), 50);
533 }
534
535 #[test]
537 fn test_constant_non_default_not_indexed_initial_source_yes() {
538 let mut context = Context::new();
539
540 for i in 0..50 {
541 if i < 10 {
542 context
543 .add_entity(with!(
544 Person,
545 ExplicitProp(1),
546 ExplicitProp2(false),
547 ConstantProp(99)
548 ))
549 .unwrap();
550 } else {
551 context
552 .add_entity(with!(Person, ExplicitProp(1), ExplicitProp2(false)))
553 .unwrap();
554 }
555 }
556
557 let results = context
558 .query_result_iterator(with!(Person, ConstantProp(99)))
559 .collect::<Vec<_>>();
560
561 assert_eq!(results.len(), 10);
562 for person in results {
563 assert_eq!(
564 context.get_property::<_, ConstantProp>(person),
565 ConstantProp(99)
566 );
567 }
568 }
569
570 #[test]
572 fn test_constant_non_default_indexed_initial_source_yes() {
573 let mut context = Context::new();
574 context.index_property::<Person, ConstantProp>();
575
576 for i in 0..50 {
577 if i < 10 {
578 context
579 .add_entity(with!(
580 Person,
581 ExplicitProp(1),
582 ExplicitProp2(false),
583 ConstantProp(99)
584 ))
585 .unwrap();
586 } else {
587 context
588 .add_entity(with!(Person, ExplicitProp(1), ExplicitProp2(false)))
589 .unwrap();
590 }
591 }
592
593 let results = context
594 .query_result_iterator(with!(Person, ConstantProp(99)))
595 .collect::<Vec<_>>();
596
597 assert_eq!(results.len(), 10);
598 }
599
600 #[test]
602 fn test_derived_not_indexed_initial_source_yes() {
603 let mut context = Context::new();
604
605 for i in 0..100 {
606 context
607 .add_entity(with!(Person, ExplicitProp(i as u8), ExplicitProp2(false)))
608 .unwrap();
609 }
610
611 let results = context
612 .query_result_iterator(with!(Person, DerivedProp(true)))
613 .collect::<Vec<_>>();
614
615 assert_eq!(results.len(), 50);
617 for person in results {
618 assert_eq!(
619 context.get_property::<Person, DerivedProp>(person),
620 DerivedProp(true)
621 );
622 }
623 }
624
625 #[test]
627 fn test_derived_indexed_initial_source_yes() {
628 let mut context = Context::new();
629 context.index_property::<Person, DerivedProp>();
630
631 for i in 0..100 {
632 context
633 .add_entity(with!(Person, ExplicitProp(i as u8), ExplicitProp2(false)))
634 .unwrap();
635 }
636
637 let results = context
638 .query_result_iterator(with!(Person, DerivedProp(false)))
639 .collect::<Vec<_>>();
640
641 assert_eq!(results.len(), 50);
643 for person in results {
644 assert_eq!(
645 context.get_property::<Person, DerivedProp>(person),
646 DerivedProp(false)
647 );
648 }
649 }
650
651 #[test]
655 fn test_explicit_non_default_not_indexed_initial_source_no() {
656 let mut context = Context::new();
657 context.index_property::<Person, ExplicitProp2>(); for i in 0..100 {
660 context
661 .add_entity(with!(
662 Person,
663 ExplicitProp((i % 20) as u8),
664 ExplicitProp2(i % 2 == 0)
665 ))
666 .unwrap();
667 }
668
669 let results = context
671 .query_result_iterator(with!(Person, ExplicitProp(5), ExplicitProp2(false)))
672 .collect::<Vec<_>>();
673
674 let expected = results.len();
678 assert!(expected > 0);
679 for person in results {
680 assert_eq!(
681 context.get_property::<Person, ExplicitProp>(person),
682 ExplicitProp(5)
683 );
684 assert_eq!(
685 context.get_property::<Person, ExplicitProp2>(person),
686 ExplicitProp2(false)
687 );
688 }
689 }
690
691 #[test]
693 fn test_explicit_non_default_indexed_initial_source_no() {
694 let mut context = Context::new();
695 context.index_property::<Person, ExplicitProp>();
696 context.index_property::<Person, ConstantProp2>(); for i in 0..100 {
699 if i < 10 {
700 context
701 .add_entity(with!(
702 Person,
703 ExplicitProp(7),
704 ExplicitProp2(false),
705 ConstantProp2(200), ))
707 .unwrap();
708 } else {
709 context
710 .add_entity(with!(
711 Person,
712 ExplicitProp((i % 20) as u8),
713 ExplicitProp2(false)
714 ))
715 .unwrap();
716 }
717 }
718
719 let results = context
720 .query_result_iterator(with!(Person, ExplicitProp(7), ConstantProp2(200)))
721 .collect::<Vec<_>>();
722
723 assert_eq!(results.len(), 10);
724 }
725
726 #[test]
728 fn test_constant_default_not_indexed_initial_source_no() {
729 let mut context = Context::new();
730 context.index_property::<Person, ExplicitProp>(); for i in 0..100 {
733 if i < 5 {
734 context
735 .add_entity(with!(Person, ExplicitProp(99), ExplicitProp2(false)))
736 .unwrap(); } else {
738 context
739 .add_entity(with!(
740 Person,
741 ExplicitProp((i % 20) as u8),
742 ExplicitProp2(false)
743 ))
744 .unwrap();
745 }
746 }
747
748 let results = context
749 .query_result_iterator(with!(Person, ExplicitProp(99), ConstantProp(42)))
750 .collect::<Vec<_>>();
751
752 assert_eq!(results.len(), 5);
753 for person in results {
754 assert_eq!(
755 context.get_property::<Person, ConstantProp>(person),
756 ConstantProp(42)
757 );
758 }
759 }
760
761 #[test]
763 fn test_constant_non_default_indexed_initial_source_no() {
764 let mut context = Context::new();
765 context.index_property::<Person, ConstantProp>();
766 context.index_property::<Person, ExplicitProp2>();
767
768 for i in 0..100 {
769 if i < 10 {
770 context
771 .add_entity(with!(
772 Person,
773 ConstantProp(99),
774 ExplicitProp(0),
775 ExplicitProp2(true)
776 ))
777 .unwrap();
778 } else {
779 context
780 .add_entity(with!(Person, ExplicitProp(0), ExplicitProp2(false)))
781 .unwrap();
782 }
783 }
784
785 let results = context
786 .query_result_iterator(with!(Person, ConstantProp(99), ExplicitProp2(true)))
787 .collect::<Vec<_>>();
788
789 assert_eq!(results.len(), 10);
790 }
791
792 #[test]
794 fn test_derived_not_indexed_initial_source_no() {
795 let mut context = Context::new();
796 context.index_property::<Person, ExplicitProp2>();
797
798 for i in 0..100 {
799 context
800 .add_entity(with!(Person, ExplicitProp(i as u8), ExplicitProp2(i < 50)))
801 .unwrap();
802 }
803
804 let results = context
805 .query_result_iterator(with!(Person, ExplicitProp2(true), DerivedProp(true)))
806 .collect::<Vec<_>>();
807
808 assert_eq!(results.len(), 25);
811 }
812
813 #[test]
815 fn test_derived_indexed_initial_source_no() {
816 let mut context = Context::new();
817 context.index_property::<Person, DerivedProp>();
818 context.index_property::<Person, ExplicitProp2>();
819
820 for i in 0..100 {
821 context
822 .add_entity(with!(Person, ExplicitProp(i as u8), ExplicitProp2(i < 30)))
823 .unwrap();
824 }
825
826 let results = context
827 .query_result_iterator(with!(Person, ExplicitProp2(true), DerivedProp(false)))
828 .collect::<Vec<_>>();
829
830 assert_eq!(results.len(), 15);
833 }
834
835 #[test]
838 fn test_multiple_query_result_iterators() {
839 let mut context = Context::new();
840 context.index_property::<Person, Age>();
841
842 for age in 0..100 {
843 context
844 .add_entity(with!(
845 Person,
846 Age(age),
847 ExplicitProp(age.wrapping_mul(7) % 100),
848 ExplicitProp2(false),
849 ))
850 .unwrap();
851 }
852 for age in 0..100 {
853 context
854 .add_entity(with!(
855 Person,
856 Age(age),
857 ExplicitProp(age.wrapping_mul(14) % 100),
858 ExplicitProp2(false),
859 ))
860 .unwrap();
861 }
862
863 let results = context.query_result_iterator(with!(Person, Age(25)));
866 let more_results = context.query_result_iterator(with!(Person, Age(25), ExplicitProp(75)));
867
868 let collected_results = results.collect::<IndexSet<_>>();
869 let other_collected_results = more_results.collect::<IndexSet<_>>();
870 let intersection_count = collected_results
871 .intersection(&other_collected_results)
872 .count();
873 assert_eq!(intersection_count, 1);
874 }
875
876 #[test]
877 fn test_expression_intersection_iteration() {
878 let set = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..10)).intersection(
879 EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..6)),
880 );
881
882 let ids = set.into_iter().collect::<Vec<_>>();
883 let expected = (0..6).map(EntityId::new).collect::<Vec<_>>();
884 assert_eq!(ids, expected);
885 }
886
887 #[test]
888 fn test_expression_difference_iteration() {
889 let set = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..5)).difference(
890 EntitySet::from_source(SourceSet::<Person>::PopulationRange(2..3)),
891 );
892
893 let ids = set.into_iter().collect::<Vec<_>>();
894 let expected = vec![
895 EntityId::new(0),
896 EntityId::new(1),
897 EntityId::new(3),
898 EntityId::new(4),
899 ];
900 assert_eq!(ids, expected);
901 }
902
903 #[test]
904 fn test_expression_union_deduplicates() {
905 let left = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..3)).difference(
906 EntitySet::from_source(SourceSet::<Person>::PopulationRange(99..100)),
907 );
908 let right = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..5)).difference(
909 EntitySet::from_source(SourceSet::<Person>::PopulationRange(99..100)),
910 );
911 let set = left.union(right);
912
913 let ids = set.into_iter().collect::<Vec<_>>();
914 let expected = (0..5).map(EntityId::new).collect::<Vec<_>>();
915 assert_eq!(ids, expected);
916 }
917
918 #[test]
919 fn test_expression_union_overlap_no_duplicates() {
920 let left = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..5)).difference(
921 EntitySet::from_source(SourceSet::<Person>::PopulationRange(4..5)),
922 );
923 let right = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..7)).difference(
924 EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..1)),
925 );
926
927 let ids = left.union(right).into_iter().collect::<IndexSet<_>>();
928 let expected = (0..7).map(EntityId::new).collect::<IndexSet<_>>();
929 assert_eq!(ids, expected);
930 }
931
932 #[test]
933 fn test_expression_intersection_of_unions() {
934 let ab = EntitySet::from_source(SourceSet::<Person>::PopulationRange(1..2))
935 .union(EntitySet::from_source(
936 SourceSet::<Person>::PopulationRange(2..3),
937 ))
938 .union(EntitySet::from_source(
939 SourceSet::<Person>::PopulationRange(3..4),
940 ));
941 let cd = EntitySet::from_source(SourceSet::<Person>::PopulationRange(2..3))
942 .union(EntitySet::from_source(
943 SourceSet::<Person>::PopulationRange(3..4),
944 ))
945 .union(EntitySet::from_source(
946 SourceSet::<Person>::PopulationRange(4..5),
947 ));
948
949 let ids = ab.intersection(cd).into_iter().collect::<Vec<_>>();
950 assert_eq!(ids, vec![EntityId::new(2), EntityId::new(3)]);
951 }
952
953 #[test]
954 fn test_expression_difference_not_commutative() {
955 let left = EntitySet::from_source(SourceSet::<Person>::PopulationRange(1..2))
956 .union(EntitySet::from_source(
957 SourceSet::<Person>::PopulationRange(2..3),
958 ))
959 .union(EntitySet::from_source(
960 SourceSet::<Person>::PopulationRange(3..4),
961 ));
962 let right = EntitySet::from_source(SourceSet::<Person>::PopulationRange(2..3))
963 .union(EntitySet::from_source(
964 SourceSet::<Person>::PopulationRange(3..4),
965 ))
966 .union(EntitySet::from_source(
967 SourceSet::<Person>::PopulationRange(4..5),
968 ));
969
970 let left_minus_right = left.difference(right).into_iter().collect::<Vec<_>>();
971 let right_minus_left = EntitySet::from_source(SourceSet::<Person>::PopulationRange(2..3))
972 .union(EntitySet::from_source(
973 SourceSet::<Person>::PopulationRange(3..4),
974 ))
975 .union(EntitySet::from_source(
976 SourceSet::<Person>::PopulationRange(4..5),
977 ))
978 .difference(
979 EntitySet::from_source(SourceSet::<Person>::PopulationRange(1..2))
980 .union(EntitySet::from_source(
981 SourceSet::<Person>::PopulationRange(2..3),
982 ))
983 .union(EntitySet::from_source(
984 SourceSet::<Person>::PopulationRange(3..4),
985 )),
986 )
987 .into_iter()
988 .collect::<Vec<_>>();
989
990 assert_eq!(left_minus_right, vec![EntityId::new(1)]);
991 assert_eq!(right_minus_left, vec![EntityId::new(4)]);
992 }
993
994 #[test]
995 fn test_union_size_hint_pending_right_is_unknown() {
996 let left = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..2)).difference(
997 EntitySet::from_source(SourceSet::<Person>::PopulationRange(99..100)),
998 );
999 let right = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..4)).difference(
1000 EntitySet::from_source(SourceSet::<Person>::PopulationRange(98..99)),
1001 );
1002 let iter = left.union(right).into_iter();
1003
1004 assert_eq!(iter.size_hint(), (4, Some(4)));
1005 }
1006
1007 #[test]
1008 fn test_nth_and_count_on_source() {
1009 let mut iter =
1010 EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..5)).into_iter();
1011 assert_eq!(iter.nth(2), Some(EntityId::new(2)));
1012
1013 let remaining = iter.count();
1014 assert_eq!(remaining, 2);
1015 }
1016
1017 #[test]
1018 fn population_range_source_iteration_and_size_hint() {
1019 let mut iter =
1020 EntitySet::from_source(SourceSet::<Person>::PopulationRange(3..7)).into_iter();
1021 assert_eq!(iter.size_hint(), (4, Some(4)));
1022 assert_eq!(iter.next(), Some(EntityId::new(3)));
1023 assert_eq!(iter.size_hint(), (3, Some(3)));
1024 assert_eq!(
1025 iter.collect::<Vec<_>>(),
1026 vec![EntityId::new(4), EntityId::new(5), EntityId::new(6)]
1027 );
1028 }
1029
1030 #[test]
1031 fn optimized_range_results_iterate_as_single_source() {
1032 let union = EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..3)).union(
1033 EntitySet::from_source(SourceSet::<Person>::PopulationRange(3..5)),
1034 );
1035 assert_eq!(
1036 union.into_iter().collect::<Vec<_>>(),
1037 vec![
1038 EntityId::new(0),
1039 EntityId::new(1),
1040 EntityId::new(2),
1041 EntityId::new(3),
1042 EntityId::new(4),
1043 ]
1044 );
1045
1046 let intersection = EntitySet::from_source(SourceSet::<Person>::PopulationRange(2..8))
1047 .intersection(EntitySet::from_source(
1048 SourceSet::<Person>::PopulationRange(4..6),
1049 ));
1050 assert_eq!(
1051 intersection.into_iter().collect::<Vec<_>>(),
1052 vec![EntityId::new(4), EntityId::new(5)]
1053 );
1054 }
1055
1056 #[test]
1057 fn split_difference_still_uses_generic_iteration_path() {
1058 let split = EntitySet::from_source(SourceSet::<Person>::PopulationRange(2..8)).difference(
1059 EntitySet::from_source(SourceSet::<Person>::PopulationRange(4..6)),
1060 );
1061 assert_eq!(
1062 split.into_iter().collect::<Vec<_>>(),
1063 vec![
1064 EntityId::new(2),
1065 EntityId::new(3),
1066 EntityId::new(6),
1067 EntityId::new(7)
1068 ]
1069 );
1070 }
1071
1072 fn finite_set(ids: &[usize]) -> FxIndexSet<EntityId<Person>> {
1073 ids.iter()
1074 .copied()
1075 .map(EntityId::new)
1076 .collect::<FxIndexSet<_>>()
1077 }
1078
1079 fn as_entity_set(set: &FxIndexSet<EntityId<Person>>) -> EntitySet<Person> {
1080 EntitySet::from_source(SourceSet::IndexSet(set))
1081 }
1082
1083 #[test]
1084 fn prototype_empty_entity_set_yields_nothing() {
1085 let ids = EntitySet::<Person>::empty().into_iter().collect::<Vec<_>>();
1086 assert!(ids.is_empty());
1087 }
1088
1089 #[test]
1090 fn prototype_iter_union_disjoint() {
1091 let a = finite_set(&[1, 2]);
1092 let b = finite_set(&[3, 4]);
1093 let ids = as_entity_set(&a)
1094 .union(as_entity_set(&b))
1095 .into_iter()
1096 .collect::<IndexSet<_>>();
1097 let expected = [1usize, 2, 3, 4]
1098 .into_iter()
1099 .map(EntityId::new)
1100 .collect::<IndexSet<_>>();
1101 assert_eq!(ids, expected);
1102 }
1103
1104 #[test]
1105 fn prototype_iter_union_overlapping() {
1106 let a = finite_set(&[1, 2, 3]);
1107 let b = finite_set(&[2, 3, 4]);
1108 let ids = as_entity_set(&a)
1109 .union(as_entity_set(&b))
1110 .into_iter()
1111 .collect::<Vec<_>>();
1112 let unique = ids.iter().copied().collect::<IndexSet<_>>();
1113 assert_eq!(ids.len(), unique.len());
1114 assert!(unique.contains(&EntityId::new(1)));
1115 assert!(unique.contains(&EntityId::new(4)));
1116 }
1117
1118 #[test]
1119 fn prototype_iter_intersection_disjoint() {
1120 let a = finite_set(&[1, 2]);
1121 let b = finite_set(&[3, 4]);
1122 let ids = as_entity_set(&a)
1123 .intersection(as_entity_set(&b))
1124 .into_iter()
1125 .collect::<Vec<_>>();
1126 assert!(ids.is_empty());
1127 }
1128
1129 #[test]
1130 fn prototype_iter_difference_basic() {
1131 let a = finite_set(&[1, 2, 3, 4]);
1132 let b = finite_set(&[3, 4, 5, 6]);
1133 let ids = as_entity_set(&a)
1134 .difference(as_entity_set(&b))
1135 .into_iter()
1136 .collect::<IndexSet<_>>();
1137 assert_eq!(ids.len(), 2);
1138 assert!(ids.contains(&EntityId::new(1)));
1139 assert!(ids.contains(&EntityId::new(2)));
1140 }
1141
1142 #[test]
1143 fn prototype_iter_matches_contains_compound() {
1144 let a = finite_set(&[1, 2, 3, 4]);
1145 let b = finite_set(&[3, 4, 5]);
1146 let c = finite_set(&[7, 8, 9, 10]);
1147 let d = finite_set(&[9, 10, 11]);
1148 let left = as_entity_set(&a).intersection(as_entity_set(&b));
1149 let right = as_entity_set(&c).difference(as_entity_set(&d));
1150 let iterated = left.union(right).into_iter().collect::<IndexSet<_>>();
1151
1152 let a2 = finite_set(&[1, 2, 3, 4]);
1153 let b2 = finite_set(&[3, 4, 5]);
1154 let c2 = finite_set(&[7, 8, 9, 10]);
1155 let d2 = finite_set(&[9, 10, 11]);
1156 let check = as_entity_set(&a2)
1157 .intersection(as_entity_set(&b2))
1158 .union(as_entity_set(&c2).difference(as_entity_set(&d2)));
1159
1160 for value in 0..15 {
1161 let entity = EntityId::new(value);
1162 assert_eq!(iterated.contains(&entity), check.contains(entity));
1163 }
1164 }
1165
1166 #[test]
1167 fn prototype_size_hint_single_source_and_partial_consume() {
1168 let mut iter =
1169 EntitySet::from_source(SourceSet::<Person>::PopulationRange(0..5)).into_iter();
1170 assert_eq!(iter.size_hint(), (5, Some(5)));
1171 iter.next();
1172 assert_eq!(iter.size_hint(), (4, Some(4)));
1173 }
1174}