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