@@ -3,22 +3,27 @@ use std::{marker::PhantomData, slice};
3
3
use crate :: {
4
4
archetype:: { ArchetypeEntity , ArchetypeId , Archetypes } ,
5
5
component:: Tick ,
6
+ entity:: Entity ,
6
7
query:: DebugCheckedUnwrap ,
7
- storage:: Tables ,
8
+ storage:: { TableId , TableRow , Tables } ,
8
9
world:: unsafe_world_cell:: UnsafeWorldCell ,
9
10
} ;
10
11
11
- use super :: { Fetchable , FetchedTerm , QueryTermGroup , TermQueryState , TermState } ;
12
+ use super :: { Fetchable , FetchedTerm , QueryTermGroup , TermQueryState , TermState , TermVec } ;
12
13
13
14
pub struct TermQueryCursor < ' w , ' s > {
15
+ table_id_iter : slice:: Iter < ' s , TableId > ,
14
16
archetype_id_iter : slice:: Iter < ' s , ArchetypeId > ,
17
+ table_entities : & ' w [ Entity ] ,
15
18
archetype_entities : & ' w [ ArchetypeEntity ] ,
16
- term_state : Vec < TermState < ' w > > ,
19
+ term_state : TermVec < TermState < ' w > > ,
17
20
current_len : usize ,
18
21
current_row : usize ,
22
+ dense : bool ,
19
23
}
20
24
21
25
impl < ' w , ' s > TermQueryCursor < ' w , ' s > {
26
+ #[ inline]
22
27
unsafe fn new < Q : QueryTermGroup > (
23
28
world : UnsafeWorldCell < ' w > ,
24
29
query_state : & ' s TermQueryState < Q > ,
@@ -27,63 +32,116 @@ impl<'w, 's> TermQueryCursor<'w, 's> {
27
32
) -> Self {
28
33
let term_state = query_state. init_term_state ( world, last_run, this_run) ;
29
34
Self {
35
+ table_id_iter : query_state. matched_table_ids . iter ( ) ,
30
36
archetype_id_iter : query_state. matched_archetype_ids . iter ( ) ,
37
+ table_entities : & [ ] ,
31
38
archetype_entities : & [ ] ,
39
+ dense : term_state. iter ( ) . all ( |t| t. dense ( ) ) ,
32
40
term_state,
33
41
current_len : 0 ,
34
42
current_row : 0 ,
35
43
}
36
44
}
37
45
46
+ #[ inline( always) ]
38
47
unsafe fn next < Q : QueryTermGroup > (
39
48
& mut self ,
40
49
tables : & ' w Tables ,
41
50
archetypes : & ' w Archetypes ,
42
51
query_state : & ' s TermQueryState < Q > ,
43
- ) -> Option < Vec < FetchedTerm < ' w > > > {
44
- loop {
45
- if self . current_row == self . current_len {
46
- let archetype_id = self . archetype_id_iter . next ( ) ?;
47
- let archetype = archetypes. get ( * archetype_id) . debug_checked_unwrap ( ) ;
48
- // SAFETY: `archetype` and `tables` are from the world that `fetch/filter` were created for,
49
- // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
50
- let table = tables. get ( archetype. table_id ( ) ) . debug_checked_unwrap ( ) ;
51
- query_state
52
+ ) -> Option < TermVec < FetchedTerm < ' w > > > {
53
+ if self . dense {
54
+ loop {
55
+ // we are on the beginning of the query, or finished processing a table, so skip to the next
56
+ if self . current_row == self . current_len {
57
+ let table_id = self . table_id_iter . next ( ) ?;
58
+ let table = tables. get ( * table_id) . debug_checked_unwrap ( ) ;
59
+ // SAFETY: `table` is from the world that `fetch/filter` were created for,
60
+ // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
61
+ query_state
62
+ . terms
63
+ . iter ( )
64
+ . zip ( self . term_state . iter_mut ( ) )
65
+ . for_each ( |( term, state) | term. set_table ( state, table) ) ;
66
+ self . table_entities = table. entities ( ) ;
67
+ self . current_len = table. entity_count ( ) ;
68
+ self . current_row = 0 ;
69
+ continue ;
70
+ }
71
+
72
+ // SAFETY: set_table was called prior.
73
+ // `current_row` is a table row in range of the current table, because if it was not, then the if above would have been executed.
74
+ let entity = * self . table_entities . get_unchecked ( self . current_row ) ;
75
+ let row = TableRow :: new ( self . current_row ) ;
76
+
77
+ // SAFETY:
78
+ // - set_table was called prior.
79
+ // - `current_row` must be a table row in range of the current table,
80
+ // because if it was not, then the if above would have been executed.
81
+ // - fetch is only called once for each `entity`.
82
+ self . current_row += 1 ;
83
+
84
+ if query_state
52
85
. terms
53
86
. iter ( )
54
87
. zip ( self . term_state . iter_mut ( ) )
55
- . for_each ( |( term, state) | term. set_table ( state, table) ) ;
56
- self . archetype_entities = archetype. entities ( ) ;
57
- self . current_len = archetype. len ( ) ;
58
- self . current_row = 0 ;
59
- continue ;
88
+ . all ( |( term, state) | term. filter_fetch ( state, entity, row) )
89
+ {
90
+ return Some (
91
+ query_state
92
+ . terms
93
+ . iter ( )
94
+ . zip ( self . term_state . iter_mut ( ) )
95
+ . map ( |( term, state) | term. fetch ( state, entity, row) )
96
+ . collect ( ) ,
97
+ ) ;
98
+ }
60
99
}
61
-
62
- // SAFETY:
63
- // - set_archetype was called prior.
64
- // - `current_row` must be an archetype index row in range of the current archetype,
65
- // because if it was not, then the if above would have been executed.
66
- // - fetch is only called once for each `archetype_entity`.
67
- let archetype_entity = self . archetype_entities . get_unchecked ( self . current_row ) ;
68
- self . current_row += 1 ;
69
-
70
- let entity = archetype_entity. entity ( ) ;
71
- let row = archetype_entity. table_row ( ) ;
72
- // Apply filters
73
- if query_state
74
- . terms
75
- . iter ( )
76
- . zip ( self . term_state . iter_mut ( ) )
77
- . all ( |( term, state) | term. filter_fetch ( state, entity, row) )
78
- {
79
- return Some (
100
+ } else {
101
+ loop {
102
+ if self . current_row == self . current_len {
103
+ let archetype_id = self . archetype_id_iter . next ( ) ?;
104
+ let archetype = archetypes. get ( * archetype_id) . debug_checked_unwrap ( ) ;
105
+ // SAFETY: `archetype` and `tables` are from the world that `fetch/filter` were created for,
106
+ // `fetch_state`/`filter_state` are the states that `fetch/filter` were initialized with
107
+ let table = tables. get ( archetype. table_id ( ) ) . debug_checked_unwrap ( ) ;
80
108
query_state
81
109
. terms
82
110
. iter ( )
83
111
. zip ( self . term_state . iter_mut ( ) )
84
- . map ( |( term, state) | term. fetch ( state, entity, row) )
85
- . collect ( ) ,
86
- ) ;
112
+ . for_each ( |( term, state) | term. set_table ( state, table) ) ;
113
+ self . archetype_entities = archetype. entities ( ) ;
114
+ self . current_len = archetype. len ( ) ;
115
+ self . current_row = 0 ;
116
+ continue ;
117
+ }
118
+
119
+ // SAFETY:
120
+ // - set_archetype was called prior.
121
+ // - `current_row` must be an archetype index row in range of the current archetype,
122
+ // because if it was not, then the if above would have been executed.
123
+ // - fetch is only called once for each `archetype_entity`.
124
+ let archetype_entity = self . archetype_entities . get_unchecked ( self . current_row ) ;
125
+ self . current_row += 1 ;
126
+
127
+ let entity = archetype_entity. entity ( ) ;
128
+ let row = archetype_entity. table_row ( ) ;
129
+ // Apply filters
130
+ if query_state
131
+ . terms
132
+ . iter ( )
133
+ . zip ( self . term_state . iter_mut ( ) )
134
+ . all ( |( term, state) | term. filter_fetch ( state, entity, row) )
135
+ {
136
+ return Some (
137
+ query_state
138
+ . terms
139
+ . iter ( )
140
+ . zip ( self . term_state . iter_mut ( ) )
141
+ . map ( |( term, state) | term. fetch ( state, entity, row) )
142
+ . collect ( ) ,
143
+ ) ;
144
+ }
87
145
}
88
146
}
89
147
}
@@ -97,6 +155,7 @@ pub struct TermQueryIterUntyped<'w, 's> {
97
155
}
98
156
99
157
impl < ' w , ' s > TermQueryIterUntyped < ' w , ' s > {
158
+ #[ inline]
100
159
pub unsafe fn new < Q : QueryTermGroup > (
101
160
world : UnsafeWorldCell < ' w > ,
102
161
query_state : & ' s TermQueryState < Q > ,
@@ -113,8 +172,9 @@ impl<'w, 's> TermQueryIterUntyped<'w, 's> {
113
172
}
114
173
115
174
impl < ' w , ' s > Iterator for TermQueryIterUntyped < ' w , ' s > {
116
- type Item = Vec < FetchedTerm < ' w > > ;
175
+ type Item = TermVec < FetchedTerm < ' w > > ;
117
176
177
+ #[ inline( always) ]
118
178
fn next ( & mut self ) -> Option < Self :: Item > {
119
179
unsafe {
120
180
self . cursor
@@ -129,6 +189,7 @@ pub struct TermQueryIter<'w, 's, Q: QueryTermGroup> {
129
189
}
130
190
131
191
impl < ' w , ' s , Q : QueryTermGroup > TermQueryIter < ' w , ' s , Q > {
192
+ #[ inline( always) ]
132
193
pub unsafe fn new (
133
194
world : UnsafeWorldCell < ' w > ,
134
195
query_state : & ' s TermQueryState < Q > ,
@@ -145,6 +206,7 @@ impl<'w, 's, Q: QueryTermGroup> TermQueryIter<'w, 's, Q> {
145
206
impl < ' w , ' s , Q : QueryTermGroup > Iterator for TermQueryIter < ' w , ' s , Q > {
146
207
type Item = Q :: Item < ' w > ;
147
208
209
+ #[ inline( always) ]
148
210
fn next ( & mut self ) -> Option < Self :: Item > {
149
211
unsafe {
150
212
self . inner
0 commit comments