Skip to main content

legion_core/
filter.rs

1use crate::index::ArchetypeIndex;
2use crate::index::ChunkIndex;
3use crate::index::SetIndex;
4use crate::iterator::FissileZip;
5use crate::iterator::SliceVecIter;
6use crate::storage::ArchetypeData;
7use crate::storage::ArchetypeId;
8use crate::storage::Component;
9use crate::storage::ComponentStorage;
10use crate::storage::ComponentTypeId;
11use crate::storage::ComponentTypes;
12use crate::storage::Storage;
13use crate::storage::Tag;
14use crate::storage::TagTypeId;
15use crate::storage::TagTypes;
16use std::iter::Enumerate;
17use std::iter::Repeat;
18use std::iter::Take;
19use std::marker::PhantomData;
20use std::slice::Iter;
21use std::sync::atomic::AtomicU64;
22use std::sync::atomic::Ordering;
23
24pub mod filter_fns {
25    ///! Contains functions for constructing filters.
26    use super::*;
27
28    pub fn passthrough() -> EntityFilterTuple<Passthrough, Passthrough, Passthrough> {
29        EntityFilterTuple::new(Passthrough, Passthrough, Passthrough)
30    }
31
32    pub fn any() -> EntityFilterTuple<Any, Any, Any> { EntityFilterTuple::new(Any, Any, Any) }
33
34    /// Creates an entity data filter which includes chunks that contain
35    /// entity data components of type `T`.
36    pub fn component<T: Component>(
37    ) -> EntityFilterTuple<ComponentFilter<T>, Passthrough, Passthrough> {
38        EntityFilterTuple::new(ComponentFilter::new(), Passthrough, Passthrough)
39    }
40
41    /// Creates a shared data filter which includes chunks that contain
42    /// shared data components of type `T`.
43    pub fn tag<T: Tag>() -> EntityFilterTuple<TagFilter<T>, Passthrough, Passthrough> {
44        EntityFilterTuple::new(TagFilter::new(), Passthrough, Passthrough)
45    }
46
47    /// Creates a shared data filter which includes chunks that contain
48    /// specific shared data values.
49    pub fn tag_value<'a, T: Tag>(
50        data: &'a T,
51    ) -> EntityFilterTuple<TagFilter<T>, TagValueFilter<'a, T>, Passthrough> {
52        EntityFilterTuple::new(TagFilter::new(), TagValueFilter::new(data), Passthrough)
53    }
54
55    /// Creates a filter which includes chunks for which entity data components
56    /// of type `T` have changed since the filter was last executed.
57    pub fn changed<T: Component>(
58    ) -> EntityFilterTuple<ComponentFilter<T>, Passthrough, ComponentChangedFilter<T>> {
59        EntityFilterTuple::new(
60            ComponentFilter::new(),
61            Passthrough,
62            ComponentChangedFilter::new(),
63        )
64    }
65}
66
67pub(crate) trait FilterResult {
68    fn coalesce_and(self, other: Self) -> Self;
69    fn coalesce_or(self, other: Self) -> Self;
70    fn is_pass(&self) -> bool;
71}
72
73impl FilterResult for Option<bool> {
74    #[inline]
75    fn coalesce_and(self, other: Self) -> Self {
76        match self {
77            Some(x) => other.map(|y| x && y).or(Some(x)),
78            None => other,
79        }
80    }
81
82    #[inline]
83    fn coalesce_or(self, other: Self) -> Self {
84        match self {
85            Some(x) => other.map(|y| x || y).or(Some(x)),
86            None => other,
87        }
88    }
89
90    #[inline]
91    fn is_pass(&self) -> bool { self.unwrap_or(true) }
92}
93
94/// A streaming iterator of bools.
95pub trait Filter<T: Copy>: Send + Sync + Sized {
96    type Iter: Iterator + Send + Sync;
97
98    // Called when a query is about to begin execution.
99    fn init(&self) {}
100
101    /// Pulls iterator data out of the source.
102    fn collect(&self, source: T) -> Self::Iter;
103
104    /// Determines if an element of `Self::Iter` matches the filter conditions.
105    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool>;
106
107    /// Creates an iterator which yields bools for each element in the source
108    /// which indicate if the element matches the filter.
109    fn matches(&mut self, source: T) -> FilterIter<Self, T> {
110        FilterIter {
111            elements: self.collect(source),
112            filter: self,
113            _phantom: PhantomData,
114        }
115    }
116}
117
118/// An iterator over the elements matching a filter.
119pub struct FilterIter<'a, F: Filter<T>, T: Copy> {
120    elements: <F as Filter<T>>::Iter,
121    filter: &'a mut F,
122    _phantom: PhantomData<T>,
123}
124
125impl<'a, F: Filter<T>, T: Copy> Iterator for FilterIter<'a, F, T> {
126    type Item = bool;
127
128    fn next(&mut self) -> Option<Self::Item> {
129        self.elements
130            .next()
131            .map(|x| self.filter.is_match(&x).is_pass())
132    }
133}
134
135impl<'a, F: Filter<T>, T: Copy + 'a> FilterIter<'a, F, T> {
136    /// Finds the indices of all elements matching the filter.
137    pub fn matching_indices(self) -> impl Iterator<Item = usize> + 'a {
138        self.enumerate().filter(|(_, x)| *x).map(|(i, _)| i)
139    }
140}
141
142/// Input data for archetype filters.
143#[derive(Copy, Clone)]
144pub struct ArchetypeFilterData<'a> {
145    /// The component types in each archetype.
146    pub component_types: &'a ComponentTypes,
147    /// The tag types in each archetype.
148    pub tag_types: &'a TagTypes,
149}
150
151/// Input data for chunkset filters.
152#[derive(Copy, Clone)]
153pub struct ChunksetFilterData<'a> {
154    /// The component data in an archetype.
155    pub archetype_data: &'a ArchetypeData,
156}
157
158/// Input data for chunk filters.
159#[derive(Copy, Clone)]
160pub struct ChunkFilterData<'a> {
161    // The components in a set
162    pub chunks: &'a [ComponentStorage],
163}
164
165/// A marker trait for filters that are not no-ops.
166pub trait ActiveFilter {}
167
168/// A type which combines both an archetype and a chunk filter.
169pub trait EntityFilter: Send + Clone {
170    type ArchetypeFilter: for<'a> Filter<ArchetypeFilterData<'a>> + Clone;
171    type ChunksetFilter: for<'a> Filter<ChunksetFilterData<'a>> + Clone;
172    type ChunkFilter: for<'a> Filter<ChunkFilterData<'a>> + Clone;
173
174    /// Initializes the entity filter for iteration.
175    fn init(&self);
176
177    /// Gets mutable references to both inner filters.
178    fn filters(
179        &self,
180    ) -> (
181        &Self::ArchetypeFilter,
182        &Self::ChunksetFilter,
183        &Self::ChunkFilter,
184    );
185
186    /// Converts self into both inner filters.
187    fn into_filters(
188        self,
189    ) -> (
190        Self::ArchetypeFilter,
191        Self::ChunksetFilter,
192        Self::ChunkFilter,
193    );
194
195    /// Gets an iterator over all matching archetype indexes.
196    fn iter_archetype_indexes<'a, 'b>(
197        &'a self,
198        storage: &'b Storage,
199    ) -> FilterArchIter<'b, 'a, Self::ArchetypeFilter>;
200
201    /// Gets an iterator over all matching chunkset indexes.
202    fn iter_chunkset_indexes<'a, 'b>(
203        &'a self,
204        archetype: &'b ArchetypeData,
205    ) -> FilterChunkIter<'b, 'a, Self::ChunksetFilter>;
206
207    /// Gets an iterator over all matching archetypes and chunksets.
208    fn iter<'a, 'b>(
209        &'a self,
210        storage: &'b Storage,
211    ) -> FilterEntityIter<'b, 'a, Self::ArchetypeFilter, Self::ChunksetFilter>;
212}
213
214/// An EntityFilter which combined both an archetype filter and a chunk filter.
215#[derive(Debug, Clone)]
216pub struct EntityFilterTuple<A, S, C> {
217    pub arch_filter: A,
218    pub chunkset_filter: S,
219    pub chunk_filter: C,
220}
221
222impl<A, S, C> EntityFilterTuple<A, S, C>
223where
224    A: for<'a> Filter<ArchetypeFilterData<'a>>,
225    S: for<'a> Filter<ChunksetFilterData<'a>>,
226    C: for<'a> Filter<ChunkFilterData<'a>>,
227{
228    /// Creates a new entity filter.
229    pub fn new(arch_filter: A, chunkset_filter: S, chunk_filter: C) -> Self {
230        Self {
231            arch_filter,
232            chunkset_filter,
233            chunk_filter,
234        }
235    }
236}
237
238impl<A, S, C> EntityFilter for EntityFilterTuple<A, S, C>
239where
240    A: for<'a> Filter<ArchetypeFilterData<'a>> + Clone,
241    S: for<'a> Filter<ChunksetFilterData<'a>> + Clone,
242    C: for<'a> Filter<ChunkFilterData<'a>> + Clone,
243{
244    type ArchetypeFilter = A;
245    type ChunksetFilter = S;
246    type ChunkFilter = C;
247
248    fn init(&self) {
249        self.arch_filter.init();
250        self.chunkset_filter.init();
251        self.chunk_filter.init();
252    }
253
254    fn filters(
255        &self,
256    ) -> (
257        &Self::ArchetypeFilter,
258        &Self::ChunksetFilter,
259        &Self::ChunkFilter,
260    ) {
261        (&self.arch_filter, &self.chunkset_filter, &self.chunk_filter)
262    }
263
264    fn into_filters(
265        self,
266    ) -> (
267        Self::ArchetypeFilter,
268        Self::ChunksetFilter,
269        Self::ChunkFilter,
270    ) {
271        (self.arch_filter, self.chunkset_filter, self.chunk_filter)
272    }
273
274    fn iter_archetype_indexes<'a, 'b>(&'a self, storage: &'b Storage) -> FilterArchIter<'b, 'a, A> {
275        let data = ArchetypeFilterData {
276            component_types: storage.component_types(),
277            tag_types: storage.tag_types(),
278        };
279
280        let iter = self.arch_filter.collect(data);
281        FilterArchIter {
282            archetypes: iter.enumerate(),
283            filter: &self.arch_filter,
284        }
285    }
286
287    fn iter_chunkset_indexes<'a, 'b>(
288        &'a self,
289        archetype: &'b ArchetypeData,
290    ) -> FilterChunkIter<'b, 'a, S> {
291        let data = ChunksetFilterData {
292            archetype_data: archetype,
293        };
294
295        let iter = self.chunkset_filter.collect(data);
296        FilterChunkIter {
297            chunks: iter.enumerate(),
298            filter: &self.chunkset_filter,
299        }
300    }
301
302    fn iter<'a, 'b>(&'a self, storage: &'b Storage) -> FilterEntityIter<'b, 'a, A, S> {
303        let data = ArchetypeFilterData {
304            component_types: storage.component_types(),
305            tag_types: storage.tag_types(),
306        };
307
308        let iter = self.arch_filter.collect(data).enumerate();
309        FilterEntityIter {
310            storage,
311            arch_filter: &self.arch_filter,
312            chunk_filter: &self.chunkset_filter,
313            archetypes: iter,
314            chunks: None,
315        }
316    }
317}
318
319impl<A, S, C> std::ops::Not for EntityFilterTuple<A, S, C>
320where
321    A: std::ops::Not,
322    S: std::ops::Not,
323    C: std::ops::Not,
324{
325    type Output = EntityFilterTuple<A::Output, S::Output, C::Output>;
326
327    #[inline]
328    fn not(self) -> Self::Output {
329        EntityFilterTuple {
330            arch_filter: !self.arch_filter,
331            chunkset_filter: !self.chunkset_filter,
332            chunk_filter: !self.chunk_filter,
333        }
334    }
335}
336
337impl<'a, A1, S1, C1, A2, S2, C2> std::ops::BitAnd<EntityFilterTuple<A2, S2, C2>>
338    for EntityFilterTuple<A1, S1, C1>
339where
340    A1: std::ops::BitAnd<A2>,
341    S1: std::ops::BitAnd<S2>,
342    C1: std::ops::BitAnd<C2>,
343{
344    type Output = EntityFilterTuple<A1::Output, S1::Output, C1::Output>;
345
346    #[inline]
347    fn bitand(self, rhs: EntityFilterTuple<A2, S2, C2>) -> Self::Output {
348        EntityFilterTuple {
349            arch_filter: self.arch_filter & rhs.arch_filter,
350            chunkset_filter: self.chunkset_filter & rhs.chunkset_filter,
351            chunk_filter: self.chunk_filter & rhs.chunk_filter,
352        }
353    }
354}
355
356impl<'a, A1, S1, C1, A2, S2, C2> std::ops::BitOr<EntityFilterTuple<A2, S2, C2>>
357    for EntityFilterTuple<A1, S1, C1>
358where
359    A1: std::ops::BitOr<A2>,
360    S1: std::ops::BitOr<S2>,
361    C1: std::ops::BitOr<C2>,
362{
363    type Output = EntityFilterTuple<A1::Output, S1::Output, C1::Output>;
364
365    #[inline]
366    fn bitor(self, rhs: EntityFilterTuple<A2, S2, C2>) -> Self::Output {
367        EntityFilterTuple {
368            arch_filter: self.arch_filter | rhs.arch_filter,
369            chunkset_filter: self.chunkset_filter | rhs.chunkset_filter,
370            chunk_filter: self.chunk_filter | rhs.chunk_filter,
371        }
372    }
373}
374
375/// An iterator which yields the indexes of archetypes that match a filter.
376pub struct FilterArchIter<'a, 'b, F: Filter<ArchetypeFilterData<'a>>> {
377    filter: &'b F,
378    archetypes: Enumerate<F::Iter>,
379}
380
381impl<'a, 'b, F: Filter<ArchetypeFilterData<'a>>> Iterator for FilterArchIter<'a, 'b, F> {
382    type Item = ArchetypeIndex;
383
384    fn next(&mut self) -> Option<Self::Item> {
385        while let Some((i, data)) = self.archetypes.next() {
386            if self.filter.is_match(&data).is_pass() {
387                return Some(ArchetypeIndex(i));
388            }
389        }
390
391        None
392    }
393}
394
395/// An iterator which yields the index of chuinks that match a filter.
396pub struct FilterChunkIter<'a, 'b, F: Filter<ChunksetFilterData<'a>>> {
397    filter: &'b F,
398    chunks: Enumerate<F::Iter>,
399}
400
401impl<'a, 'b, F: Filter<ChunksetFilterData<'a>>> Iterator for FilterChunkIter<'a, 'b, F> {
402    type Item = SetIndex;
403
404    fn next(&mut self) -> Option<Self::Item> {
405        if let Some((i, data)) = self.chunks.next() {
406            if self.filter.is_match(&data).is_pass() {
407                return Some(SetIndex(i));
408            }
409        }
410
411        None
412    }
413}
414
415/// An iterator which yields the IDs of chunks that match an entity filter.
416pub struct FilterEntityIter<
417    'a,
418    'b,
419    Arch: Filter<ArchetypeFilterData<'a>>,
420    Chunk: Filter<ChunksetFilterData<'a>>,
421> {
422    storage: &'a Storage,
423    arch_filter: &'b Arch,
424    chunk_filter: &'b Chunk,
425    archetypes: Enumerate<Arch::Iter>,
426    chunks: Option<(ArchetypeId, Enumerate<Chunk::Iter>)>,
427}
428
429impl<'a, 'b, Arch: Filter<ArchetypeFilterData<'a>>, Chunk: Filter<ChunksetFilterData<'a>>> Iterator
430    for FilterEntityIter<'a, 'b, Arch, Chunk>
431{
432    type Item = (ArchetypeId, ChunkIndex);
433
434    fn next(&mut self) -> Option<Self::Item> {
435        loop {
436            if let Some((arch_id, ref mut chunks)) = self.chunks {
437                for (chunk_index, chunk_data) in chunks {
438                    if self.chunk_filter.is_match(&chunk_data).is_pass() {
439                        return Some((arch_id, ChunkIndex(chunk_index)));
440                    }
441                }
442            }
443            loop {
444                match self.archetypes.next() {
445                    Some((arch_index, arch_data)) => {
446                        if self.arch_filter.is_match(&arch_data).is_pass() {
447                            self.chunks = {
448                                let archetype =
449                                    unsafe { self.storage.archetypes().get_unchecked(arch_index) };
450                                let data = ChunksetFilterData {
451                                    archetype_data: archetype,
452                                };
453
454                                Some((archetype.id(), self.chunk_filter.collect(data).enumerate()))
455                            };
456                            break;
457                        }
458                    }
459                    None => return None,
460                }
461            }
462        }
463    }
464}
465
466/// A passthrough filter which allows through all elements.
467#[derive(Debug, Clone)]
468pub struct Passthrough;
469
470impl<'a> Filter<ArchetypeFilterData<'a>> for Passthrough {
471    type Iter = Take<Repeat<()>>;
472
473    #[inline]
474    fn init(&self) {}
475
476    #[inline]
477    fn collect(&self, arch: ArchetypeFilterData<'a>) -> Self::Iter {
478        std::iter::repeat(()).take(arch.component_types.len())
479    }
480
481    #[inline]
482    fn is_match(&self, _: &<Self::Iter as Iterator>::Item) -> Option<bool> { None }
483}
484
485impl<'a> Filter<ChunksetFilterData<'a>> for Passthrough {
486    type Iter = Take<Repeat<()>>;
487
488    #[inline]
489    fn init(&self) {}
490
491    #[inline]
492    fn collect(&self, sets: ChunksetFilterData<'a>) -> Self::Iter {
493        std::iter::repeat(()).take(sets.archetype_data.len())
494    }
495
496    #[inline]
497    fn is_match(&self, _: &<Self::Iter as Iterator>::Item) -> Option<bool> { None }
498}
499
500impl<'a> Filter<ChunkFilterData<'a>> for Passthrough {
501    type Iter = Take<Repeat<()>>;
502
503    #[inline]
504    fn init(&self) {}
505
506    #[inline]
507    fn collect(&self, chunk: ChunkFilterData<'a>) -> Self::Iter {
508        std::iter::repeat(()).take(chunk.chunks.len())
509    }
510
511    #[inline]
512    fn is_match(&self, _: &<Self::Iter as Iterator>::Item) -> Option<bool> { None }
513}
514
515impl std::ops::Not for Passthrough {
516    type Output = Passthrough;
517
518    #[inline]
519    fn not(self) -> Self::Output { self }
520}
521
522impl<'a, Rhs> std::ops::BitAnd<Rhs> for Passthrough {
523    type Output = Rhs;
524
525    #[inline]
526    fn bitand(self, rhs: Rhs) -> Self::Output { rhs }
527}
528
529impl<'a, Rhs> std::ops::BitOr<Rhs> for Passthrough {
530    type Output = Rhs;
531
532    #[inline]
533    fn bitor(self, rhs: Rhs) -> Self::Output { rhs }
534}
535
536#[derive(Debug, Clone)]
537pub struct Any;
538
539impl ActiveFilter for Any {}
540
541impl<'a> Filter<ArchetypeFilterData<'a>> for Any {
542    type Iter = Take<Repeat<()>>;
543
544    #[inline]
545    fn init(&self) {}
546
547    #[inline]
548    fn collect(&self, arch: ArchetypeFilterData<'a>) -> Self::Iter {
549        std::iter::repeat(()).take(arch.component_types.len())
550    }
551
552    #[inline]
553    fn is_match(&self, _: &<Self::Iter as Iterator>::Item) -> Option<bool> { Some(true) }
554}
555
556impl<'a> Filter<ChunksetFilterData<'a>> for Any {
557    type Iter = Take<Repeat<()>>;
558
559    #[inline]
560    fn init(&self) {}
561
562    #[inline]
563    fn collect(&self, sets: ChunksetFilterData<'a>) -> Self::Iter {
564        std::iter::repeat(()).take(sets.archetype_data.len())
565    }
566
567    #[inline]
568    fn is_match(&self, _: &<Self::Iter as Iterator>::Item) -> Option<bool> { Some(true) }
569}
570
571impl<'a> Filter<ChunkFilterData<'a>> for Any {
572    type Iter = Take<Repeat<()>>;
573
574    #[inline]
575    fn init(&self) {}
576
577    #[inline]
578    fn collect(&self, chunk: ChunkFilterData<'a>) -> Self::Iter {
579        std::iter::repeat(()).take(chunk.chunks.len())
580    }
581
582    #[inline]
583    fn is_match(&self, _: &<Self::Iter as Iterator>::Item) -> Option<bool> { Some(true) }
584}
585
586impl<Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for Any {
587    type Output = Rhs;
588
589    #[inline]
590    fn bitand(self, rhs: Rhs) -> Self::Output { rhs }
591}
592
593impl std::ops::BitAnd<Passthrough> for Any {
594    type Output = Self;
595
596    #[inline]
597    fn bitand(self, _: Passthrough) -> Self::Output { self }
598}
599
600impl<Rhs: ActiveFilter> std::ops::BitOr<Rhs> for Any {
601    type Output = Self;
602
603    #[inline]
604    fn bitor(self, _: Rhs) -> Self::Output { self }
605}
606
607impl std::ops::BitOr<Passthrough> for Any {
608    type Output = Self;
609
610    #[inline]
611    fn bitor(self, _: Passthrough) -> Self::Output { self }
612}
613
614/// A filter which negates `F`.
615#[derive(Debug, Clone)]
616pub struct Not<F> {
617    pub filter: F,
618}
619
620impl<F> ActiveFilter for Not<F> {}
621
622impl<'a, T: Copy, F: Filter<T>> Filter<T> for Not<F> {
623    type Iter = F::Iter;
624
625    #[inline]
626    fn init(&self) { self.filter.init(); }
627
628    #[inline]
629    fn collect(&self, source: T) -> Self::Iter { self.filter.collect(source) }
630
631    #[inline]
632    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
633        self.filter.is_match(item).map(|x| !x)
634    }
635}
636
637impl<'a, F, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for Not<F> {
638    type Output = And<(Self, Rhs)>;
639
640    #[inline]
641    fn bitand(self, rhs: Rhs) -> Self::Output {
642        And {
643            filters: (self, rhs),
644        }
645    }
646}
647
648impl<'a, F> std::ops::BitAnd<Passthrough> for Not<F> {
649    type Output = Self;
650
651    #[inline]
652    fn bitand(self, _: Passthrough) -> Self::Output { self }
653}
654
655impl<'a, F, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for Not<F> {
656    type Output = Or<(Self, Rhs)>;
657
658    #[inline]
659    fn bitor(self, rhs: Rhs) -> Self::Output {
660        Or {
661            filters: (self, rhs),
662        }
663    }
664}
665
666impl<'a, F> std::ops::BitOr<Passthrough> for Not<F> {
667    type Output = Self;
668
669    #[inline]
670    fn bitor(self, _: Passthrough) -> Self::Output { self }
671}
672
673/// A filter which requires all filters within `T` match.
674#[derive(Debug, Clone)]
675pub struct And<T> {
676    pub filters: T,
677}
678
679impl<T> ActiveFilter for And<(T,)> {}
680
681impl<'a, T: Copy, F: Filter<T>> Filter<T> for And<(F,)> {
682    type Iter = F::Iter;
683
684    #[inline]
685    fn init(&self) { self.filters.0.init(); }
686
687    #[inline]
688    fn collect(&self, source: T) -> Self::Iter { self.filters.0.collect(source) }
689
690    #[inline]
691    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
692        self.filters.0.is_match(item)
693    }
694}
695
696impl<T> std::ops::Not for And<(T,)> {
697    type Output = Not<Self>;
698
699    #[inline]
700    fn not(self) -> Self::Output { Not { filter: self } }
701}
702
703impl<T, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for And<(T,)> {
704    type Output = And<(T, Rhs)>;
705
706    #[inline]
707    fn bitand(self, rhs: Rhs) -> Self::Output {
708        And {
709            filters: (self.filters.0, rhs),
710        }
711    }
712}
713
714impl<T> std::ops::BitAnd<Passthrough> for And<(T,)> {
715    type Output = Self;
716
717    #[inline]
718    fn bitand(self, _: Passthrough) -> Self::Output { self }
719}
720
721impl<T, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for And<(T,)> {
722    type Output = Or<(Self, Rhs)>;
723
724    #[inline]
725    fn bitor(self, rhs: Rhs) -> Self::Output {
726        Or {
727            filters: (self, rhs),
728        }
729    }
730}
731
732impl<T> std::ops::BitOr<Passthrough> for And<(T,)> {
733    type Output = Self;
734
735    #[inline]
736    fn bitor(self, _: Passthrough) -> Self::Output { self }
737}
738
739macro_rules! recursive_zip {
740    (@value $first:expr, $($rest:expr),*) => { FissileZip::new($first, recursive_zip!(@value $($rest),*)) };
741    (@value $last:expr) => { $last };
742    (@type $first:ty, $($rest:ty),*) => { FissileZip<$first, recursive_zip!(@type $($rest),*)> };
743    (@type $last:ty) => { $last };
744    (@unzip $first:ident, $($rest:ident),*) => { ($first, recursive_zip!(@unzip $($rest),*)) };
745    (@unzip $last:ident) => { $last };
746}
747
748macro_rules! impl_and_filter {
749    ( $( $ty: ident => $ty2: ident ),* ) => {
750        impl<$( $ty ),*> ActiveFilter for And<($( $ty, )*)> {}
751
752        impl<'a, T: Copy, $( $ty: Filter<T> ),*> Filter<T> for And<($( $ty, )*)> {
753            // type Iter = crate::zip::Zip<( $( $ty::Iter ),* )>;
754            type Iter = recursive_zip!(@type $($ty::Iter),*);
755
756            #[inline]
757            fn init(&self) {
758                #![allow(non_snake_case)]
759                let ($( $ty, )*) = &self.filters;
760                $( $ty.init(); )*
761            }
762
763            fn collect(&self, source: T) -> Self::Iter {
764                #![allow(non_snake_case)]
765                let ($( $ty, )*) = &self.filters;
766                // let iters = (
767                //     $( $ty.collect(source) ),*
768                // );
769                // crate::zip::multizip(iters)
770                recursive_zip!(@value $($ty.collect(source)),*)
771            }
772
773            #[inline]
774            fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
775                #![allow(non_snake_case)]
776                let ($( $ty, )*) = &self.filters;
777                // let ($( $ty2, )*) = item;
778                let recursive_zip!(@unzip $($ty2),*) = item;
779                let mut result: Option<bool> = None;
780                $( result = result.coalesce_and($ty.is_match($ty2)); )*
781                result
782            }
783        }
784
785        impl<$( $ty ),*> std::ops::Not for And<($( $ty, )*)> {
786            type Output = Not<Self>;
787
788            #[inline]
789            fn not(self) -> Self::Output {
790                Not { filter: self }
791            }
792        }
793
794        impl<$( $ty ),*, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for And<($( $ty, )*)> {
795            type Output = And<($( $ty, )* Rhs)>;
796
797            #[inline]
798            fn bitand(self, rhs: Rhs) -> Self::Output {
799                #![allow(non_snake_case)]
800                let ($( $ty, )*) = self.filters;
801                And {
802                    filters: ($( $ty, )* rhs),
803                }
804            }
805        }
806
807        impl<$( $ty ),*> std::ops::BitAnd<Passthrough> for And<($( $ty, )*)> {
808            type Output = Self;
809
810            #[inline]
811            fn bitand(self, _: Passthrough) -> Self::Output {
812                self
813            }
814        }
815
816        impl<$( $ty ),*, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for And<($( $ty, )*)> {
817            type Output = Or<(Self, Rhs)>;
818
819            #[inline]
820            fn bitor(self, rhs: Rhs) -> Self::Output {
821                Or {
822                    filters: (self, rhs),
823                }
824            }
825        }
826
827        impl<$( $ty ),*> std::ops::BitOr<Passthrough> for And<($( $ty, )*)> {
828            type Output = Self;
829
830            #[inline]
831            fn bitor(self, _: Passthrough) -> Self::Output {
832                self
833            }
834        }
835    }
836}
837
838impl_and_filter!(A => a, B => b);
839impl_and_filter!(A => a, B => b, C => c);
840impl_and_filter!(A => a, B => b, C => c, D => d);
841impl_and_filter!(A => a, B => b, C => c, D => d, E => e);
842impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f);
843impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g);
844impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h);
845impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i);
846impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i, J => j);
847impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i, J => j, K => k);
848impl_and_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i, J => j, K => k, L => l);
849
850/// A filter which requires that any filter within `T` match.
851#[derive(Debug, Clone)]
852pub struct Or<T> {
853    pub filters: T,
854}
855
856macro_rules! impl_or_filter {
857    ( $( $ty: ident => $ty2: ident ),* ) => {
858        impl<$( $ty ),*> ActiveFilter for Or<($( $ty, )*)> {}
859
860        impl<'a, T: Copy, $( $ty: Filter<T> ),*> Filter<T> for Or<($( $ty, )*)> {
861            // type Iter = crate::zip::Zip<( $( $ty::Iter ),* )>;
862            type Iter = recursive_zip!(@type $($ty::Iter),*);
863
864            #[inline]
865            fn init(&self) {
866                #![allow(non_snake_case)]
867                let ($( $ty, )*) = &self.filters;
868                $( $ty.init(); )*
869            }
870
871            fn collect(&self, source: T) -> Self::Iter {
872                #![allow(non_snake_case)]
873                let ($( $ty, )*) = &self.filters;
874                // let iters = (
875                //     $( $ty.collect(source) ),*
876                // );
877                // crate::zip::multizip(iters)
878                recursive_zip!(@value $($ty.collect(source)),*)
879            }
880
881            #[inline]
882            fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
883                #![allow(non_snake_case)]
884                let ($( $ty, )*) = &self.filters;
885                // let ($( $ty2, )*) = item;
886                let recursive_zip!(@unzip $($ty2),*) = item;
887                let mut result: Option<bool> = None;
888                $( result = result.coalesce_or($ty.is_match($ty2)); )*
889                result
890            }
891        }
892
893        impl<$( $ty ),*> std::ops::Not for Or<($( $ty, )*)> {
894            type Output = Not<Self>;
895
896            #[inline]
897            fn not(self) -> Self::Output {
898                Not { filter: self }
899            }
900        }
901
902        impl<$( $ty ),*, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for Or<($( $ty, )*)> {
903            type Output = And<(Self, Rhs)>;
904
905            #[inline]
906            fn bitand(self, rhs: Rhs) -> Self::Output {
907                And {
908                    filters: (self, rhs),
909                }
910            }
911        }
912
913        impl<$( $ty ),*> std::ops::BitAnd<Passthrough> for Or<($( $ty, )*)> {
914            type Output = Self;
915
916            #[inline]
917            fn bitand(self, _: Passthrough) -> Self::Output {
918                self
919            }
920        }
921
922        impl<$( $ty ),*, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for Or<($( $ty, )*)> {
923            type Output = Or<($( $ty, )* Rhs)>;
924
925            #[inline]
926            fn bitor(self, rhs: Rhs) -> Self::Output {
927                #![allow(non_snake_case)]
928                let ($( $ty, )*) = self.filters;
929                Or {
930                    filters: ($( $ty, )* rhs),
931                }
932            }
933        }
934
935        impl<$( $ty ),*> std::ops::BitOr<Passthrough> for Or<($( $ty, )*)> {
936            type Output = Self;
937
938            #[inline]
939            fn bitor(self, _: Passthrough) -> Self::Output {
940                self
941            }
942        }
943    }
944}
945
946impl_or_filter!(A => a, B => b);
947impl_or_filter!(A => a, B => b, C => c);
948impl_or_filter!(A => a, B => b, C => c, D => d);
949impl_or_filter!(A => a, B => b, C => c, D => d, E => e);
950impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f);
951impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g);
952impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h);
953impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i);
954impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i, J => j);
955impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i, J => j, K => k);
956impl_or_filter!(A => a, B => b, C => c, D => d, E => e, F => f, G => g, H => h, I => i, J => j, K => k, L => l);
957
958/// A filter qhich requires that all chunks contain entity data components of type `T`.
959#[derive(Debug)]
960pub struct ComponentFilter<T>(PhantomData<T>);
961
962impl<T: Component> ComponentFilter<T> {
963    fn new() -> Self { ComponentFilter(PhantomData) }
964}
965
966impl<T> ActiveFilter for ComponentFilter<T> {}
967
968impl<T> Copy for ComponentFilter<T> {}
969impl<T> Clone for ComponentFilter<T> {
970    fn clone(&self) -> Self { *self }
971}
972
973impl<'a, T: Component> Filter<ArchetypeFilterData<'a>> for ComponentFilter<T> {
974    type Iter = SliceVecIter<'a, ComponentTypeId>;
975
976    #[inline]
977    fn init(&self) {}
978
979    #[inline]
980    fn collect(&self, source: ArchetypeFilterData<'a>) -> Self::Iter {
981        source.component_types.iter()
982    }
983
984    #[inline]
985    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
986        Some(item.contains(&ComponentTypeId::of::<T>()))
987    }
988}
989
990impl<T> std::ops::Not for ComponentFilter<T> {
991    type Output = Not<Self>;
992
993    #[inline]
994    fn not(self) -> Self::Output { Not { filter: self } }
995}
996
997impl<'a, T, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for ComponentFilter<T> {
998    type Output = And<(Self, Rhs)>;
999
1000    #[inline]
1001    fn bitand(self, rhs: Rhs) -> Self::Output {
1002        And {
1003            filters: (self, rhs),
1004        }
1005    }
1006}
1007
1008impl<'a, T> std::ops::BitAnd<Passthrough> for ComponentFilter<T> {
1009    type Output = Self;
1010
1011    #[inline]
1012    fn bitand(self, _: Passthrough) -> Self::Output { self }
1013}
1014
1015impl<'a, T, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for ComponentFilter<T> {
1016    type Output = Or<(Self, Rhs)>;
1017
1018    #[inline]
1019    fn bitor(self, rhs: Rhs) -> Self::Output {
1020        Or {
1021            filters: (self, rhs),
1022        }
1023    }
1024}
1025
1026impl<'a, T> std::ops::BitOr<Passthrough> for ComponentFilter<T> {
1027    type Output = Self;
1028
1029    #[inline]
1030    fn bitor(self, _: Passthrough) -> Self::Output { self }
1031}
1032
1033/// A filter which requires that all chunks contain shared tag data of type `T`.
1034#[derive(Debug)]
1035pub struct TagFilter<T>(PhantomData<T>);
1036
1037impl<T: Tag> TagFilter<T> {
1038    fn new() -> Self { TagFilter(PhantomData) }
1039}
1040
1041impl<T> ActiveFilter for TagFilter<T> {}
1042
1043impl<T> Copy for TagFilter<T> {}
1044impl<T> Clone for TagFilter<T> {
1045    fn clone(&self) -> Self { *self }
1046}
1047
1048impl<'a, T: Tag> Filter<ArchetypeFilterData<'a>> for TagFilter<T> {
1049    type Iter = SliceVecIter<'a, TagTypeId>;
1050
1051    #[inline]
1052    fn init(&self) {}
1053
1054    #[inline]
1055    fn collect(&self, source: ArchetypeFilterData<'a>) -> Self::Iter { source.tag_types.iter() }
1056
1057    #[inline]
1058    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
1059        Some(item.contains(&TagTypeId::of::<T>()))
1060    }
1061}
1062
1063impl<T> std::ops::Not for TagFilter<T> {
1064    type Output = Not<Self>;
1065
1066    #[inline]
1067    fn not(self) -> Self::Output { Not { filter: self } }
1068}
1069
1070impl<'a, T, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for TagFilter<T> {
1071    type Output = And<(Self, Rhs)>;
1072
1073    #[inline]
1074    fn bitand(self, rhs: Rhs) -> Self::Output {
1075        And {
1076            filters: (self, rhs),
1077        }
1078    }
1079}
1080
1081impl<'a, T> std::ops::BitAnd<Passthrough> for TagFilter<T> {
1082    type Output = Self;
1083
1084    #[inline]
1085    fn bitand(self, _: Passthrough) -> Self::Output { self }
1086}
1087
1088impl<'a, T, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for TagFilter<T> {
1089    type Output = Or<(Self, Rhs)>;
1090
1091    #[inline]
1092    fn bitor(self, rhs: Rhs) -> Self::Output {
1093        Or {
1094            filters: (self, rhs),
1095        }
1096    }
1097}
1098
1099impl<'a, T> std::ops::BitOr<Passthrough> for TagFilter<T> {
1100    type Output = Self;
1101
1102    #[inline]
1103    fn bitor(self, _: Passthrough) -> Self::Output { self }
1104}
1105
1106/// A filter which requires that all chunks contain a specific tag value.
1107#[derive(Debug)]
1108pub struct TagValueFilter<'a, T> {
1109    value: &'a T,
1110}
1111
1112impl<'a, T: Tag> TagValueFilter<'a, T> {
1113    fn new(value: &'a T) -> Self { TagValueFilter { value } }
1114}
1115
1116impl<'a, T> ActiveFilter for TagValueFilter<'a, T> {}
1117
1118impl<'a, T> Copy for TagValueFilter<'a, T> {}
1119impl<'a, T> Clone for TagValueFilter<'a, T> {
1120    fn clone(&self) -> Self { *self }
1121}
1122
1123impl<'a, 'b, T: Tag> Filter<ChunksetFilterData<'a>> for TagValueFilter<'b, T> {
1124    type Iter = Iter<'a, T>;
1125
1126    #[inline]
1127    fn init(&self) {}
1128
1129    fn collect(&self, source: ChunksetFilterData<'a>) -> Self::Iter {
1130        unsafe {
1131            source
1132                .archetype_data
1133                .tags()
1134                .get(TagTypeId::of::<T>())
1135                .unwrap()
1136                .data_slice::<T>()
1137                .iter()
1138        }
1139    }
1140
1141    #[inline]
1142    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
1143        Some(**item == *self.value)
1144    }
1145}
1146
1147impl<'a, T> std::ops::Not for TagValueFilter<'a, T> {
1148    type Output = Not<Self>;
1149
1150    #[inline]
1151    fn not(self) -> Self::Output { Not { filter: self } }
1152}
1153
1154impl<'a, T, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for TagValueFilter<'a, T> {
1155    type Output = And<(Self, Rhs)>;
1156
1157    #[inline]
1158    fn bitand(self, rhs: Rhs) -> Self::Output {
1159        And {
1160            filters: (self, rhs),
1161        }
1162    }
1163}
1164
1165impl<'a, T> std::ops::BitAnd<Passthrough> for TagValueFilter<'a, T> {
1166    type Output = Self;
1167
1168    #[inline]
1169    fn bitand(self, _: Passthrough) -> Self::Output { self }
1170}
1171
1172impl<'a, T, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for TagValueFilter<'a, T> {
1173    type Output = Or<(Self, Rhs)>;
1174
1175    #[inline]
1176    fn bitor(self, rhs: Rhs) -> Self::Output {
1177        Or {
1178            filters: (self, rhs),
1179        }
1180    }
1181}
1182
1183impl<'a, T> std::ops::BitOr<Passthrough> for TagValueFilter<'a, T> {
1184    type Output = Self;
1185
1186    #[inline]
1187    fn bitor(self, _: Passthrough) -> Self::Output { self }
1188}
1189
1190/// A filter which requires that entity data of type `T` has changed within the
1191/// chunk since the last time the filter was executed.
1192#[derive(Debug)]
1193pub struct ComponentChangedFilter<T: Component> {
1194    high_water_mark: AtomicU64,
1195    version_threshold: AtomicU64,
1196    phantom: PhantomData<T>,
1197}
1198
1199impl<T: Component> ComponentChangedFilter<T> {
1200    fn new() -> ComponentChangedFilter<T> {
1201        ComponentChangedFilter {
1202            high_water_mark: AtomicU64::new(0),
1203            version_threshold: AtomicU64::new(0),
1204            phantom: PhantomData,
1205        }
1206    }
1207}
1208
1209impl<T: Component> ActiveFilter for ComponentChangedFilter<T> {}
1210
1211impl<T: Component> Clone for ComponentChangedFilter<T> {
1212    fn clone(&self) -> Self {
1213        Self {
1214            high_water_mark: AtomicU64::new(self.high_water_mark.load(Ordering::Relaxed)),
1215            version_threshold: AtomicU64::new(self.version_threshold.load(Ordering::Relaxed)),
1216            phantom: PhantomData,
1217        }
1218    }
1219}
1220
1221impl<'a, T: Component> Filter<ChunkFilterData<'a>> for ComponentChangedFilter<T> {
1222    type Iter = ComponentChangedState<'a, ComponentStorage>;
1223
1224    #[inline]
1225    fn init(&self) {
1226        let version = self.high_water_mark.load(Ordering::Relaxed);
1227        let mut threshold = self.version_threshold.load(Ordering::Relaxed);
1228        if threshold < version {
1229            loop {
1230                match self.version_threshold.compare_exchange_weak(
1231                    threshold,
1232                    version,
1233                    Ordering::Relaxed,
1234                    Ordering::Relaxed,
1235                ) {
1236                    Ok(_) => break,
1237                    Err(stored_last_read) => {
1238                        threshold = stored_last_read;
1239                        if threshold >= version {
1240                            // matched version is already considered visited, update no longer needed
1241                            break;
1242                        }
1243                    }
1244                }
1245            }
1246        }
1247    }
1248
1249    fn collect(&self, source: ChunkFilterData<'a>) -> Self::Iter {
1250        let compare_version = self.version_threshold.load(Ordering::Relaxed);
1251        ComponentChangedState {
1252            iter: source.chunks.iter(),
1253            version_threshold: compare_version,
1254        }
1255    }
1256
1257    #[inline]
1258    fn is_match(&self, item: &<Self::Iter as Iterator>::Item) -> Option<bool> {
1259        let (version_threshold, storage) = item;
1260
1261        let components = storage.components(ComponentTypeId::of::<T>());
1262        if components.is_none() {
1263            return Some(false);
1264        }
1265
1266        let version = components.unwrap().version();
1267        let mut last_read = self.high_water_mark.load(Ordering::Relaxed);
1268        if last_read < version {
1269            loop {
1270                match self.high_water_mark.compare_exchange_weak(
1271                    last_read,
1272                    version,
1273                    Ordering::Relaxed,
1274                    Ordering::Relaxed,
1275                ) {
1276                    Ok(_) => break,
1277                    Err(stored_last_read) => {
1278                        last_read = stored_last_read;
1279                        if last_read >= version {
1280                            // matched version is already considered visited, update no longer needed
1281                            break;
1282                        }
1283                    }
1284                }
1285            }
1286        }
1287
1288        if version > *version_threshold {
1289            Some(true)
1290        } else {
1291            Some(false)
1292        }
1293    }
1294}
1295
1296pub struct ComponentChangedState<'a, T: Component> {
1297    iter: Iter<'a, T>,
1298    version_threshold: u64,
1299}
1300
1301impl<'a, T: Component> Iterator for ComponentChangedState<'a, T> {
1302    type Item = (u64, &'a T);
1303
1304    fn next(&mut self) -> Option<Self::Item> {
1305        self.iter.next().map(|c| (self.version_threshold, c))
1306    }
1307}
1308
1309impl<'a, T: Component> std::ops::Not for ComponentChangedFilter<T> {
1310    type Output = Not<Self>;
1311
1312    #[inline]
1313    fn not(self) -> Self::Output { Not { filter: self } }
1314}
1315
1316impl<'a, T: Component, Rhs: ActiveFilter> std::ops::BitAnd<Rhs> for ComponentChangedFilter<T> {
1317    type Output = And<(Self, Rhs)>;
1318
1319    #[inline]
1320    fn bitand(self, rhs: Rhs) -> Self::Output {
1321        And {
1322            filters: (self, rhs),
1323        }
1324    }
1325}
1326
1327impl<'a, T: Component> std::ops::BitAnd<Passthrough> for ComponentChangedFilter<T> {
1328    type Output = Self;
1329
1330    #[inline]
1331    fn bitand(self, _: Passthrough) -> Self::Output { self }
1332}
1333
1334impl<'a, T: Component, Rhs: ActiveFilter> std::ops::BitOr<Rhs> for ComponentChangedFilter<T> {
1335    type Output = Or<(Self, Rhs)>;
1336
1337    #[inline]
1338    fn bitor(self, rhs: Rhs) -> Self::Output {
1339        Or {
1340            filters: (self, rhs),
1341        }
1342    }
1343}
1344
1345impl<'a, T: Component> std::ops::BitOr<Passthrough> for ComponentChangedFilter<T> {
1346    type Output = Self;
1347
1348    #[inline]
1349    fn bitor(self, _: Passthrough) -> Self::Output { self }
1350}
1351
1352#[cfg(test)]
1353mod test {
1354    use super::filter_fns::*;
1355    use crate::prelude::*;
1356
1357    #[test]
1358    pub fn create() {
1359        let _ = tracing_subscriber::fmt::try_init();
1360
1361        let filter = component::<usize>() | tag_value(&5isize);
1362        tracing::trace!(?filter);
1363    }
1364
1365    #[test]
1366    fn component_changed_filter() {
1367        let _ = tracing_subscriber::fmt::try_init();
1368
1369        let universe = Universe::new();
1370        let mut world = universe.create_world();
1371
1372        let entity1 = world.insert((), vec![(1usize,)])[0];
1373        let entity2 = world.insert((), vec![(2usize, false)])[0];
1374
1375        let query = <Read<usize>>::query().filter(changed::<usize>());
1376
1377        assert_eq!(2, query.iter_chunks(&world).collect::<Vec<_>>().len());
1378
1379        *world.get_component_mut::<usize>(entity1).unwrap() = 3usize;
1380
1381        assert_eq!(1, query.iter_chunks(&world).collect::<Vec<_>>().len());
1382
1383        *world.get_component_mut::<usize>(entity1).unwrap() = 4usize;
1384        *world.get_component_mut::<usize>(entity2).unwrap() = 5usize;
1385
1386        assert_eq!(2, query.iter_chunks(&world).collect::<Vec<_>>().len());
1387
1388        *world.get_component_mut::<usize>(entity1).unwrap() = 6usize;
1389        *world.get_component_mut::<usize>(entity1).unwrap() = 7usize;
1390        *world.get_component_mut::<usize>(entity2).unwrap() = 8usize;
1391
1392        assert_eq!(2, query.iter_chunks(&world).collect::<Vec<_>>().len());
1393
1394        *world.get_component_mut::<usize>(entity2).unwrap() = 6usize;
1395        *world.get_component_mut::<usize>(entity2).unwrap() = 7usize;
1396        *world.get_component_mut::<usize>(entity1).unwrap() = 8usize;
1397
1398        assert_eq!(2, query.iter_chunks(&world).collect::<Vec<_>>().len());
1399    }
1400}