• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mlange-42 / ark / 13597253646

28 Feb 2025 10:03PM CUT coverage: 96.9% (-0.09%) from 96.988%
13597253646

Pull #82

github

web-flow
Merge 52c6f9ea6 into 5263582b2
Pull Request #82: Unsafe filter and query

234 of 242 new or added lines in 3 files covered. (96.69%)

17 existing lines in 1 file now uncovered.

3626 of 3742 relevant lines covered (96.9%)

50664.41 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.06
/ecs/query_gen.go
1
package ecs
2

3
// Code generated by go generate; DO NOT EDIT.
4

5
type cursor struct {
6
        archetype int
7
        table     int
8
        index     uintptr
9
        maxIndex  int64
10
}
11

12
// Query0 is a query for 0 components.
13
// Use a [NewFilter0] to create one.
14
type Query0 struct {
15
        world      *World
16
        filter     Filter
17
        relations  []RelationID
18
        lock       uint8
19
        cursor     cursor
20
        tables     []tableID
21
        table      *table
22
        components []*componentStorage
23
        hasWithout bool
24
}
25

26
func newQuery0(world *World, filter Filter, relations []RelationID) Query0 {
8✔
27
        components := make([]*componentStorage, 0)
8✔
28

8✔
29
        return Query0{
8✔
30
                world:      world,
8✔
31
                filter:     filter,
8✔
32
                relations:  relations,
8✔
33
                lock:       world.lock(),
8✔
34
                components: components,
8✔
35
                cursor: cursor{
8✔
36
                        archetype: -1,
8✔
37
                        table:     -1,
8✔
38
                        index:     0,
8✔
39
                        maxIndex:  -1,
8✔
40
                },
8✔
41
        }
8✔
42
}
8✔
43

44
// Next advances the query's cursor to the next entity.
45
func (q *Query0) Next() bool {
192✔
46
        q.world.checkQueryNext(&q.cursor)
192✔
47
        if int64(q.cursor.index) < q.cursor.maxIndex {
365✔
48
                q.cursor.index++
173✔
49
                return true
173✔
50
        }
173✔
51
        return q.nextTableOrArchetype()
19✔
52
}
53

54
// Entity returns the current entity.
55
func (q *Query0) Entity() Entity {
185✔
56
        q.world.checkQueryGet(&q.cursor)
185✔
57
        return q.table.GetEntity(q.cursor.index)
185✔
58
}
185✔
59

60
// Close closes the Query and unlocks the world.
61
//
62
// Automatically called when iteration finishes.
63
// Needs to be called only if breaking out of the query iteration or not iterating at all.
64
func (q *Query0) Close() {
8✔
65
        q.cursor.archetype = -2
8✔
66
        q.cursor.table = -2
8✔
67
        q.tables = nil
8✔
68
        q.table = nil
8✔
69
        q.world.unlock(q.lock)
8✔
70
}
8✔
71

72
func (q *Query0) nextTableOrArchetype() bool {
19✔
73
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
74
                return true
2✔
75
        }
2✔
76
        return q.nextArchetype()
17✔
77
}
78

79
func (q *Query0) nextArchetype() bool {
17✔
80
        maxArchIndex := len(q.world.storage.archetypes) - 1
17✔
81
        for q.cursor.archetype < maxArchIndex {
34✔
82
                q.cursor.archetype++
17✔
83
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
17✔
84
                if !q.filter.matches(&archetype.mask) {
21✔
85
                        continue
4✔
86
                }
87

88
                if !archetype.HasRelations() {
23✔
89
                        table := &q.world.storage.tables[archetype.tables[0]]
11✔
90
                        if table.Len() > 0 {
18✔
91
                                q.setTable(0, table)
7✔
92
                                return true
7✔
93
                        }
7✔
94
                        continue
4✔
95
                }
96

97
                q.tables = archetype.GetTables(q.relations)
1✔
98
                q.cursor.table = -1
1✔
99
                if q.nextTable() {
2✔
100
                        return true
1✔
101
                }
1✔
102
        }
103
        q.Close()
8✔
104
        return false
8✔
105
}
106

107
func (q *Query0) nextTable() bool {
11✔
108
        maxTableIndex := len(q.tables) - 1
11✔
109
        for q.cursor.table < maxTableIndex {
14✔
110
                q.cursor.table++
3✔
111
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
3✔
112
                if table.Len() == 0 {
3✔
UNCOV
113
                        continue
×
114
                }
115
                if !table.Matches(q.relations) {
3✔
UNCOV
116
                        continue
×
117
                }
118
                q.setTable(q.cursor.table, table)
3✔
119
                return true
3✔
120
        }
121
        return false
8✔
122
}
123

124
func (q *Query0) setTable(index int, table *table) {
10✔
125
        q.cursor.table = index
10✔
126
        q.table = table
10✔
127
        q.cursor.index = 0
10✔
128
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
129
}
10✔
130

131
// Query1 is a query for 1 components.
132
// Use a [NewFilter1] to create one.
133
type Query1[A any] struct {
134
        world      *World
135
        filter     Filter
136
        relations  []RelationID
137
        lock       uint8
138
        cursor     cursor
139
        tables     []tableID
140
        table      *table
141
        components []*componentStorage
142
        columnA    *column
143
        hasWithout bool
144
}
145

146
func newQuery1[A any](world *World, filter Filter, ids []ID, relations []RelationID) Query1[A] {
1,009✔
147
        components := make([]*componentStorage, 1)
1,009✔
148
        for i := range 1 {
2,018✔
149
                components[i] = &world.storage.components[ids[i].id]
1,009✔
150
        }
1,009✔
151

152
        return Query1[A]{
1,009✔
153
                world:      world,
1,009✔
154
                filter:     filter,
1,009✔
155
                relations:  relations,
1,009✔
156
                lock:       world.lock(),
1,009✔
157
                components: components,
1,009✔
158
                cursor: cursor{
1,009✔
159
                        archetype: -1,
1,009✔
160
                        table:     -1,
1,009✔
161
                        index:     0,
1,009✔
162
                        maxIndex:  -1,
1,009✔
163
                },
1,009✔
164
        }
1,009✔
165
}
166

167
// Next advances the query's cursor to the next entity.
168
func (q *Query1[A]) Next() bool {
1,032,656✔
169
        q.world.checkQueryNext(&q.cursor)
1,032,656✔
170
        if int64(q.cursor.index) < q.cursor.maxIndex {
2,063,292✔
171
                q.cursor.index++
1,030,636✔
172
                return true
1,030,636✔
173
        }
1,030,636✔
174
        return q.nextTableOrArchetype()
2,020✔
175
}
176

177
// Entity returns the current entity.
178
func (q *Query1[A]) Entity() Entity {
2,063,142✔
179
        q.world.checkQueryGet(&q.cursor)
2,063,142✔
180
        return q.table.GetEntity(q.cursor.index)
2,063,142✔
181
}
2,063,142✔
182

183
// Get returns the queried components of the current entity.
184
func (q *Query1[A]) Get() *A {
1,031,648✔
185
        q.world.checkQueryGet(&q.cursor)
1,031,648✔
186
        return (*A)(q.columnA.Get(q.cursor.index))
1,031,648✔
187
}
1,031,648✔
188

189
// GetRelation returns the entity relation target of the component at the given index.
190
func (q *Query1[A]) GetRelation(index int) Entity {
10✔
191
        return q.components[index].columns[q.table.id].target
10✔
192
}
10✔
193

194
// Close closes the Query and unlocks the world.
195
//
196
// Automatically called when iteration finishes.
197
// Needs to be called only if breaking out of the query iteration or not iterating at all.
198
func (q *Query1[A]) Close() {
1,009✔
199
        q.cursor.archetype = -2
1,009✔
200
        q.cursor.table = -2
1,009✔
201
        q.tables = nil
1,009✔
202
        q.table = nil
1,009✔
203
        q.columnA = nil
1,009✔
204
        q.world.unlock(q.lock)
1,009✔
205
}
1,009✔
206

207
func (q *Query1[A]) nextTableOrArchetype() bool {
2,020✔
208
        if q.cursor.archetype >= 0 && q.nextTable() {
2,021✔
209
                return true
1✔
210
        }
1✔
211
        return q.nextArchetype()
2,019✔
212
}
213

214
func (q *Query1[A]) nextArchetype() bool {
2,019✔
215
        maxArchIndex := len(q.world.storage.archetypes) - 1
2,019✔
216
        for q.cursor.archetype < maxArchIndex {
4,042✔
217
                q.cursor.archetype++
2,023✔
218
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
2,023✔
219
                if !q.filter.matches(&archetype.mask) {
3,036✔
220
                        continue
1,013✔
221
                }
222

223
                if !archetype.HasRelations() {
2,016✔
224
                        table := &q.world.storage.tables[archetype.tables[0]]
1,007✔
225
                        if table.Len() > 0 {
2,014✔
226
                                q.setTable(0, table)
1,007✔
227
                                return true
1,007✔
228
                        }
1,007✔
UNCOV
229
                        continue
×
230
                }
231

232
                q.tables = archetype.GetTables(q.relations)
2✔
233
                q.cursor.table = -1
2✔
234
                if q.nextTable() {
4✔
235
                        return true
2✔
236
                }
2✔
237
        }
238
        q.Close()
1,009✔
239
        return false
1,009✔
240
}
241

242
func (q *Query1[A]) nextTable() bool {
1,012✔
243
        maxTableIndex := len(q.tables) - 1
1,012✔
244
        for q.cursor.table < maxTableIndex {
1,016✔
245
                q.cursor.table++
4✔
246
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
247
                if table.Len() == 0 {
5✔
248
                        continue
1✔
249
                }
250
                if !table.Matches(q.relations) {
3✔
UNCOV
251
                        continue
×
252
                }
253
                q.setTable(q.cursor.table, table)
3✔
254
                return true
3✔
255
        }
256
        return false
1,009✔
257
}
258

259
func (q *Query1[A]) setTable(index int, table *table) {
1,010✔
260
        q.cursor.table = index
1,010✔
261
        q.table = table
1,010✔
262
        q.columnA = q.components[0].columns[q.table.id]
1,010✔
263
        q.cursor.index = 0
1,010✔
264
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
1,010✔
265
}
1,010✔
266

267
// Query2 is a query for 2 components.
268
// Use a [NewFilter2] to create one.
269
type Query2[A any, B any] struct {
270
        world      *World
271
        filter     Filter
272
        relations  []RelationID
273
        lock       uint8
274
        cursor     cursor
275
        tables     []tableID
276
        table      *table
277
        components []*componentStorage
278
        columnA    *column
279
        columnB    *column
280
        hasWithout bool
281
}
282

283
func newQuery2[A any, B any](world *World, filter Filter, ids []ID, relations []RelationID) Query2[A, B] {
10✔
284
        components := make([]*componentStorage, 2)
10✔
285
        for i := range 2 {
30✔
286
                components[i] = &world.storage.components[ids[i].id]
20✔
287
        }
20✔
288

289
        return Query2[A, B]{
10✔
290
                world:      world,
10✔
291
                filter:     filter,
10✔
292
                relations:  relations,
10✔
293
                lock:       world.lock(),
10✔
294
                components: components,
10✔
295
                cursor: cursor{
10✔
296
                        archetype: -1,
10✔
297
                        table:     -1,
10✔
298
                        index:     0,
10✔
299
                        maxIndex:  -1,
10✔
300
                },
10✔
301
        }
10✔
302
}
303

304
// Next advances the query's cursor to the next entity.
305
func (q *Query2[A, B]) Next() bool {
195✔
306
        q.world.checkQueryNext(&q.cursor)
195✔
307
        if int64(q.cursor.index) < q.cursor.maxIndex {
368✔
308
                q.cursor.index++
173✔
309
                return true
173✔
310
        }
173✔
311
        return q.nextTableOrArchetype()
22✔
312
}
313

314
// Entity returns the current entity.
315
func (q *Query2[A, B]) Entity() Entity {
154✔
316
        q.world.checkQueryGet(&q.cursor)
154✔
317
        return q.table.GetEntity(q.cursor.index)
154✔
318
}
154✔
319

320
// Get returns the queried components of the current entity.
321
func (q *Query2[A, B]) Get() (*A, *B) {
186✔
322
        q.world.checkQueryGet(&q.cursor)
186✔
323
        return (*A)(q.columnA.Get(q.cursor.index)),
186✔
324
                (*B)(q.columnB.Get(q.cursor.index))
186✔
325
}
186✔
326

327
// GetRelation returns the entity relation target of the component at the given index.
328
func (q *Query2[A, B]) GetRelation(index int) Entity {
10✔
329
        return q.components[index].columns[q.table.id].target
10✔
330
}
10✔
331

332
// Close closes the Query and unlocks the world.
333
//
334
// Automatically called when iteration finishes.
335
// Needs to be called only if breaking out of the query iteration or not iterating at all.
336
func (q *Query2[A, B]) Close() {
10✔
337
        q.cursor.archetype = -2
10✔
338
        q.cursor.table = -2
10✔
339
        q.tables = nil
10✔
340
        q.table = nil
10✔
341
        q.columnA = nil
10✔
342
        q.columnB = nil
10✔
343
        q.world.unlock(q.lock)
10✔
344
}
10✔
345

346
func (q *Query2[A, B]) nextTableOrArchetype() bool {
22✔
347
        if q.cursor.archetype >= 0 && q.nextTable() {
23✔
348
                return true
1✔
349
        }
1✔
350
        return q.nextArchetype()
21✔
351
}
352

353
func (q *Query2[A, B]) nextArchetype() bool {
21✔
354
        maxArchIndex := len(q.world.storage.archetypes) - 1
21✔
355
        for q.cursor.archetype < maxArchIndex {
50✔
356
                q.cursor.archetype++
29✔
357
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
29✔
358
                if !q.filter.matches(&archetype.mask) {
47✔
359
                        continue
18✔
360
                }
361

362
                if !archetype.HasRelations() {
17✔
363
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
364
                        if table.Len() > 0 {
14✔
365
                                q.setTable(0, table)
7✔
366
                                return true
7✔
367
                        }
7✔
UNCOV
368
                        continue
×
369
                }
370

371
                q.tables = archetype.GetTables(q.relations)
3✔
372
                q.cursor.table = -1
3✔
373
                if q.nextTable() {
6✔
374
                        return true
3✔
375
                }
3✔
376
        }
377
        q.Close()
10✔
378
        return false
10✔
379
}
380

381
func (q *Query2[A, B]) nextTable() bool {
14✔
382
        maxTableIndex := len(q.tables) - 1
14✔
383
        for q.cursor.table < maxTableIndex {
19✔
384
                q.cursor.table++
5✔
385
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
5✔
386
                if table.Len() == 0 {
6✔
387
                        continue
1✔
388
                }
389
                if !table.Matches(q.relations) {
4✔
UNCOV
390
                        continue
×
391
                }
392
                q.setTable(q.cursor.table, table)
4✔
393
                return true
4✔
394
        }
395
        return false
10✔
396
}
397

398
func (q *Query2[A, B]) setTable(index int, table *table) {
11✔
399
        q.cursor.table = index
11✔
400
        q.table = table
11✔
401
        q.columnA = q.components[0].columns[q.table.id]
11✔
402
        q.columnB = q.components[1].columns[q.table.id]
11✔
403
        q.cursor.index = 0
11✔
404
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
11✔
405
}
11✔
406

407
// Query3 is a query for 3 components.
408
// Use a [NewFilter3] to create one.
409
type Query3[A any, B any, C any] struct {
410
        world      *World
411
        filter     Filter
412
        relations  []RelationID
413
        lock       uint8
414
        cursor     cursor
415
        tables     []tableID
416
        table      *table
417
        components []*componentStorage
418
        columnA    *column
419
        columnB    *column
420
        columnC    *column
421
        hasWithout bool
422
}
423

424
func newQuery3[A any, B any, C any](world *World, filter Filter, ids []ID, relations []RelationID) Query3[A, B, C] {
12✔
425
        components := make([]*componentStorage, 3)
12✔
426
        for i := range 3 {
48✔
427
                components[i] = &world.storage.components[ids[i].id]
36✔
428
        }
36✔
429

430
        return Query3[A, B, C]{
12✔
431
                world:      world,
12✔
432
                filter:     filter,
12✔
433
                relations:  relations,
12✔
434
                lock:       world.lock(),
12✔
435
                components: components,
12✔
436
                cursor: cursor{
12✔
437
                        archetype: -1,
12✔
438
                        table:     -1,
12✔
439
                        index:     0,
12✔
440
                        maxIndex:  -1,
12✔
441
                },
12✔
442
        }
12✔
443
}
444

445
// Next advances the query's cursor to the next entity.
446
func (q *Query3[A, B, C]) Next() bool {
235✔
447
        q.world.checkQueryNext(&q.cursor)
235✔
448
        if int64(q.cursor.index) < q.cursor.maxIndex {
440✔
449
                q.cursor.index++
205✔
450
                return true
205✔
451
        }
205✔
452
        return q.nextTableOrArchetype()
30✔
453
}
454

455
// Entity returns the current entity.
456
func (q *Query3[A, B, C]) Entity() Entity {
154✔
457
        q.world.checkQueryGet(&q.cursor)
154✔
458
        return q.table.GetEntity(q.cursor.index)
154✔
459
}
154✔
460

461
// Get returns the queried components of the current entity.
462
func (q *Query3[A, B, C]) Get() (*A, *B, *C) {
154✔
463
        q.world.checkQueryGet(&q.cursor)
154✔
464
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
465
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
466
                (*C)(q.columnC.Get(q.cursor.index))
154✔
467
}
154✔
468

469
// GetRelation returns the entity relation target of the component at the given index.
470
func (q *Query3[A, B, C]) GetRelation(index int) Entity {
10✔
471
        return q.components[index].columns[q.table.id].target
10✔
472
}
10✔
473

474
// Close closes the Query and unlocks the world.
475
//
476
// Automatically called when iteration finishes.
477
// Needs to be called only if breaking out of the query iteration or not iterating at all.
478
func (q *Query3[A, B, C]) Close() {
12✔
479
        q.cursor.archetype = -2
12✔
480
        q.cursor.table = -2
12✔
481
        q.tables = nil
12✔
482
        q.table = nil
12✔
483
        q.columnA = nil
12✔
484
        q.columnB = nil
12✔
485
        q.columnC = nil
12✔
486
        q.world.unlock(q.lock)
12✔
487
}
12✔
488

489
func (q *Query3[A, B, C]) nextTableOrArchetype() bool {
30✔
490
        if q.cursor.archetype >= 0 && q.nextTable() {
35✔
491
                return true
5✔
492
        }
5✔
493
        return q.nextArchetype()
25✔
494
}
495

496
func (q *Query3[A, B, C]) nextArchetype() bool {
25✔
497
        maxArchIndex := len(q.world.storage.archetypes) - 1
25✔
498
        for q.cursor.archetype < maxArchIndex {
58✔
499
                q.cursor.archetype++
33✔
500
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
33✔
501
                if !q.filter.matches(&archetype.mask) {
53✔
502
                        continue
20✔
503
                }
504

505
                if !archetype.HasRelations() {
19✔
506
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
507
                        if table.Len() > 0 {
14✔
508
                                q.setTable(0, table)
7✔
509
                                return true
7✔
510
                        }
7✔
UNCOV
511
                        continue
×
512
                }
513

514
                q.tables = archetype.GetTables(q.relations)
5✔
515
                q.cursor.table = -1
5✔
516
                if q.nextTable() {
10✔
517
                        return true
5✔
518
                }
5✔
519
        }
520
        q.Close()
12✔
521
        return false
12✔
522
}
523

524
func (q *Query3[A, B, C]) nextTable() bool {
22✔
525
        maxTableIndex := len(q.tables) - 1
22✔
526
        for q.cursor.table < maxTableIndex {
34✔
527
                q.cursor.table++
12✔
528
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
12✔
529
                if table.Len() == 0 {
13✔
530
                        continue
1✔
531
                }
532
                if !table.Matches(q.relations) {
12✔
533
                        continue
1✔
534
                }
535
                q.setTable(q.cursor.table, table)
10✔
536
                return true
10✔
537
        }
538
        return false
12✔
539
}
540

541
func (q *Query3[A, B, C]) setTable(index int, table *table) {
17✔
542
        q.cursor.table = index
17✔
543
        q.table = table
17✔
544
        q.columnA = q.components[0].columns[q.table.id]
17✔
545
        q.columnB = q.components[1].columns[q.table.id]
17✔
546
        q.columnC = q.components[2].columns[q.table.id]
17✔
547
        q.cursor.index = 0
17✔
548
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
17✔
549
}
17✔
550

551
// Query4 is a query for 4 components.
552
// Use a [NewFilter4] to create one.
553
type Query4[A any, B any, C any, D any] struct {
554
        world      *World
555
        filter     Filter
556
        relations  []RelationID
557
        lock       uint8
558
        cursor     cursor
559
        tables     []tableID
560
        table      *table
561
        components []*componentStorage
562
        columnA    *column
563
        columnB    *column
564
        columnC    *column
565
        columnD    *column
566
        hasWithout bool
567
}
568

569
func newQuery4[A any, B any, C any, D any](world *World, filter Filter, ids []ID, relations []RelationID) Query4[A, B, C, D] {
9✔
570
        components := make([]*componentStorage, 4)
9✔
571
        for i := range 4 {
45✔
572
                components[i] = &world.storage.components[ids[i].id]
36✔
573
        }
36✔
574

575
        return Query4[A, B, C, D]{
9✔
576
                world:      world,
9✔
577
                filter:     filter,
9✔
578
                relations:  relations,
9✔
579
                lock:       world.lock(),
9✔
580
                components: components,
9✔
581
                cursor: cursor{
9✔
582
                        archetype: -1,
9✔
583
                        table:     -1,
9✔
584
                        index:     0,
9✔
585
                        maxIndex:  -1,
9✔
586
                },
9✔
587
        }
9✔
588
}
589

590
// Next advances the query's cursor to the next entity.
591
func (q *Query4[A, B, C, D]) Next() bool {
162✔
592
        q.world.checkQueryNext(&q.cursor)
162✔
593
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
594
                q.cursor.index++
142✔
595
                return true
142✔
596
        }
142✔
597
        return q.nextTableOrArchetype()
20✔
598
}
599

600
// Entity returns the current entity.
601
func (q *Query4[A, B, C, D]) Entity() Entity {
154✔
602
        q.world.checkQueryGet(&q.cursor)
154✔
603
        return q.table.GetEntity(q.cursor.index)
154✔
604
}
154✔
605

606
// Get returns the queried components of the current entity.
607
func (q *Query4[A, B, C, D]) Get() (*A, *B, *C, *D) {
154✔
608
        q.world.checkQueryGet(&q.cursor)
154✔
609
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
610
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
611
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
612
                (*D)(q.columnD.Get(q.cursor.index))
154✔
613
}
154✔
614

615
// GetRelation returns the entity relation target of the component at the given index.
616
func (q *Query4[A, B, C, D]) GetRelation(index int) Entity {
10✔
617
        return q.components[index].columns[q.table.id].target
10✔
618
}
10✔
619

620
// Close closes the Query and unlocks the world.
621
//
622
// Automatically called when iteration finishes.
623
// Needs to be called only if breaking out of the query iteration or not iterating at all.
624
func (q *Query4[A, B, C, D]) Close() {
9✔
625
        q.cursor.archetype = -2
9✔
626
        q.cursor.table = -2
9✔
627
        q.tables = nil
9✔
628
        q.table = nil
9✔
629
        q.columnA = nil
9✔
630
        q.columnB = nil
9✔
631
        q.columnC = nil
9✔
632
        q.columnD = nil
9✔
633
        q.world.unlock(q.lock)
9✔
634
}
9✔
635

636
func (q *Query4[A, B, C, D]) nextTableOrArchetype() bool {
20✔
637
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
638
                return true
1✔
639
        }
1✔
640
        return q.nextArchetype()
19✔
641
}
642

643
func (q *Query4[A, B, C, D]) nextArchetype() bool {
19✔
644
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
645
        for q.cursor.archetype < maxArchIndex {
46✔
646
                q.cursor.archetype++
27✔
647
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
648
                if !q.filter.matches(&archetype.mask) {
44✔
649
                        continue
17✔
650
                }
651

652
                if !archetype.HasRelations() {
16✔
653
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
654
                        if table.Len() > 0 {
14✔
655
                                q.setTable(0, table)
7✔
656
                                return true
7✔
657
                        }
7✔
UNCOV
658
                        continue
×
659
                }
660

661
                q.tables = archetype.GetTables(q.relations)
2✔
662
                q.cursor.table = -1
2✔
663
                if q.nextTable() {
4✔
664
                        return true
2✔
665
                }
2✔
666
        }
667
        q.Close()
9✔
668
        return false
9✔
669
}
670

671
func (q *Query4[A, B, C, D]) nextTable() bool {
12✔
672
        maxTableIndex := len(q.tables) - 1
12✔
673
        for q.cursor.table < maxTableIndex {
16✔
674
                q.cursor.table++
4✔
675
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
676
                if table.Len() == 0 {
5✔
677
                        continue
1✔
678
                }
679
                if !table.Matches(q.relations) {
3✔
UNCOV
680
                        continue
×
681
                }
682
                q.setTable(q.cursor.table, table)
3✔
683
                return true
3✔
684
        }
685
        return false
9✔
686
}
687

688
func (q *Query4[A, B, C, D]) setTable(index int, table *table) {
10✔
689
        q.cursor.table = index
10✔
690
        q.table = table
10✔
691
        q.columnA = q.components[0].columns[q.table.id]
10✔
692
        q.columnB = q.components[1].columns[q.table.id]
10✔
693
        q.columnC = q.components[2].columns[q.table.id]
10✔
694
        q.columnD = q.components[3].columns[q.table.id]
10✔
695
        q.cursor.index = 0
10✔
696
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
697
}
10✔
698

699
// Query5 is a query for 5 components.
700
// Use a [NewFilter5] to create one.
701
type Query5[A any, B any, C any, D any, E any] struct {
702
        world      *World
703
        filter     Filter
704
        relations  []RelationID
705
        lock       uint8
706
        cursor     cursor
707
        tables     []tableID
708
        table      *table
709
        components []*componentStorage
710
        columnA    *column
711
        columnB    *column
712
        columnC    *column
713
        columnD    *column
714
        columnE    *column
715
        hasWithout bool
716
}
717

718
func newQuery5[A any, B any, C any, D any, E any](world *World, filter Filter, ids []ID, relations []RelationID) Query5[A, B, C, D, E] {
9✔
719
        components := make([]*componentStorage, 5)
9✔
720
        for i := range 5 {
54✔
721
                components[i] = &world.storage.components[ids[i].id]
45✔
722
        }
45✔
723

724
        return Query5[A, B, C, D, E]{
9✔
725
                world:      world,
9✔
726
                filter:     filter,
9✔
727
                relations:  relations,
9✔
728
                lock:       world.lock(),
9✔
729
                components: components,
9✔
730
                cursor: cursor{
9✔
731
                        archetype: -1,
9✔
732
                        table:     -1,
9✔
733
                        index:     0,
9✔
734
                        maxIndex:  -1,
9✔
735
                },
9✔
736
        }
9✔
737
}
738

739
// Next advances the query's cursor to the next entity.
740
func (q *Query5[A, B, C, D, E]) Next() bool {
162✔
741
        q.world.checkQueryNext(&q.cursor)
162✔
742
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
743
                q.cursor.index++
142✔
744
                return true
142✔
745
        }
142✔
746
        return q.nextTableOrArchetype()
20✔
747
}
748

749
// Entity returns the current entity.
750
func (q *Query5[A, B, C, D, E]) Entity() Entity {
154✔
751
        q.world.checkQueryGet(&q.cursor)
154✔
752
        return q.table.GetEntity(q.cursor.index)
154✔
753
}
154✔
754

755
// Get returns the queried components of the current entity.
756
func (q *Query5[A, B, C, D, E]) Get() (*A, *B, *C, *D, *E) {
154✔
757
        q.world.checkQueryGet(&q.cursor)
154✔
758
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
759
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
760
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
761
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
762
                (*E)(q.columnE.Get(q.cursor.index))
154✔
763
}
154✔
764

765
// GetRelation returns the entity relation target of the component at the given index.
766
func (q *Query5[A, B, C, D, E]) GetRelation(index int) Entity {
10✔
767
        return q.components[index].columns[q.table.id].target
10✔
768
}
10✔
769

770
// Close closes the Query and unlocks the world.
771
//
772
// Automatically called when iteration finishes.
773
// Needs to be called only if breaking out of the query iteration or not iterating at all.
774
func (q *Query5[A, B, C, D, E]) Close() {
9✔
775
        q.cursor.archetype = -2
9✔
776
        q.cursor.table = -2
9✔
777
        q.tables = nil
9✔
778
        q.table = nil
9✔
779
        q.columnA = nil
9✔
780
        q.columnB = nil
9✔
781
        q.columnC = nil
9✔
782
        q.columnD = nil
9✔
783
        q.columnE = nil
9✔
784
        q.world.unlock(q.lock)
9✔
785
}
9✔
786

787
func (q *Query5[A, B, C, D, E]) nextTableOrArchetype() bool {
20✔
788
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
789
                return true
1✔
790
        }
1✔
791
        return q.nextArchetype()
19✔
792
}
793

794
func (q *Query5[A, B, C, D, E]) nextArchetype() bool {
19✔
795
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
796
        for q.cursor.archetype < maxArchIndex {
46✔
797
                q.cursor.archetype++
27✔
798
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
799
                if !q.filter.matches(&archetype.mask) {
44✔
800
                        continue
17✔
801
                }
802

803
                if !archetype.HasRelations() {
16✔
804
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
805
                        if table.Len() > 0 {
14✔
806
                                q.setTable(0, table)
7✔
807
                                return true
7✔
808
                        }
7✔
UNCOV
809
                        continue
×
810
                }
811

812
                q.tables = archetype.GetTables(q.relations)
2✔
813
                q.cursor.table = -1
2✔
814
                if q.nextTable() {
4✔
815
                        return true
2✔
816
                }
2✔
817
        }
818
        q.Close()
9✔
819
        return false
9✔
820
}
821

822
func (q *Query5[A, B, C, D, E]) nextTable() bool {
12✔
823
        maxTableIndex := len(q.tables) - 1
12✔
824
        for q.cursor.table < maxTableIndex {
16✔
825
                q.cursor.table++
4✔
826
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
827
                if table.Len() == 0 {
5✔
828
                        continue
1✔
829
                }
830
                if !table.Matches(q.relations) {
3✔
UNCOV
831
                        continue
×
832
                }
833
                q.setTable(q.cursor.table, table)
3✔
834
                return true
3✔
835
        }
836
        return false
9✔
837
}
838

839
func (q *Query5[A, B, C, D, E]) setTable(index int, table *table) {
10✔
840
        q.cursor.table = index
10✔
841
        q.table = table
10✔
842
        q.columnA = q.components[0].columns[q.table.id]
10✔
843
        q.columnB = q.components[1].columns[q.table.id]
10✔
844
        q.columnC = q.components[2].columns[q.table.id]
10✔
845
        q.columnD = q.components[3].columns[q.table.id]
10✔
846
        q.columnE = q.components[4].columns[q.table.id]
10✔
847
        q.cursor.index = 0
10✔
848
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
849
}
10✔
850

851
// Query6 is a query for 6 components.
852
// Use a [NewFilter6] to create one.
853
type Query6[A any, B any, C any, D any, E any, F any] struct {
854
        world      *World
855
        filter     Filter
856
        relations  []RelationID
857
        lock       uint8
858
        cursor     cursor
859
        tables     []tableID
860
        table      *table
861
        components []*componentStorage
862
        columnA    *column
863
        columnB    *column
864
        columnC    *column
865
        columnD    *column
866
        columnE    *column
867
        columnF    *column
868
        hasWithout bool
869
}
870

871
func newQuery6[A any, B any, C any, D any, E any, F any](world *World, filter Filter, ids []ID, relations []RelationID) Query6[A, B, C, D, E, F] {
9✔
872
        components := make([]*componentStorage, 6)
9✔
873
        for i := range 6 {
63✔
874
                components[i] = &world.storage.components[ids[i].id]
54✔
875
        }
54✔
876

877
        return Query6[A, B, C, D, E, F]{
9✔
878
                world:      world,
9✔
879
                filter:     filter,
9✔
880
                relations:  relations,
9✔
881
                lock:       world.lock(),
9✔
882
                components: components,
9✔
883
                cursor: cursor{
9✔
884
                        archetype: -1,
9✔
885
                        table:     -1,
9✔
886
                        index:     0,
9✔
887
                        maxIndex:  -1,
9✔
888
                },
9✔
889
        }
9✔
890
}
891

892
// Next advances the query's cursor to the next entity.
893
func (q *Query6[A, B, C, D, E, F]) Next() bool {
162✔
894
        q.world.checkQueryNext(&q.cursor)
162✔
895
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
896
                q.cursor.index++
142✔
897
                return true
142✔
898
        }
142✔
899
        return q.nextTableOrArchetype()
20✔
900
}
901

902
// Entity returns the current entity.
903
func (q *Query6[A, B, C, D, E, F]) Entity() Entity {
154✔
904
        q.world.checkQueryGet(&q.cursor)
154✔
905
        return q.table.GetEntity(q.cursor.index)
154✔
906
}
154✔
907

908
// Get returns the queried components of the current entity.
909
func (q *Query6[A, B, C, D, E, F]) Get() (*A, *B, *C, *D, *E, *F) {
154✔
910
        q.world.checkQueryGet(&q.cursor)
154✔
911
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
912
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
913
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
914
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
915
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
916
                (*F)(q.columnF.Get(q.cursor.index))
154✔
917
}
154✔
918

919
// GetRelation returns the entity relation target of the component at the given index.
920
func (q *Query6[A, B, C, D, E, F]) GetRelation(index int) Entity {
10✔
921
        return q.components[index].columns[q.table.id].target
10✔
922
}
10✔
923

924
// Close closes the Query and unlocks the world.
925
//
926
// Automatically called when iteration finishes.
927
// Needs to be called only if breaking out of the query iteration or not iterating at all.
928
func (q *Query6[A, B, C, D, E, F]) Close() {
9✔
929
        q.cursor.archetype = -2
9✔
930
        q.cursor.table = -2
9✔
931
        q.tables = nil
9✔
932
        q.table = nil
9✔
933
        q.columnA = nil
9✔
934
        q.columnB = nil
9✔
935
        q.columnC = nil
9✔
936
        q.columnD = nil
9✔
937
        q.columnE = nil
9✔
938
        q.columnF = nil
9✔
939
        q.world.unlock(q.lock)
9✔
940
}
9✔
941

942
func (q *Query6[A, B, C, D, E, F]) nextTableOrArchetype() bool {
20✔
943
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
944
                return true
1✔
945
        }
1✔
946
        return q.nextArchetype()
19✔
947
}
948

949
func (q *Query6[A, B, C, D, E, F]) nextArchetype() bool {
19✔
950
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
951
        for q.cursor.archetype < maxArchIndex {
46✔
952
                q.cursor.archetype++
27✔
953
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
954
                if !q.filter.matches(&archetype.mask) {
44✔
955
                        continue
17✔
956
                }
957

958
                if !archetype.HasRelations() {
16✔
959
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
960
                        if table.Len() > 0 {
14✔
961
                                q.setTable(0, table)
7✔
962
                                return true
7✔
963
                        }
7✔
UNCOV
964
                        continue
×
965
                }
966

967
                q.tables = archetype.GetTables(q.relations)
2✔
968
                q.cursor.table = -1
2✔
969
                if q.nextTable() {
4✔
970
                        return true
2✔
971
                }
2✔
972
        }
973
        q.Close()
9✔
974
        return false
9✔
975
}
976

977
func (q *Query6[A, B, C, D, E, F]) nextTable() bool {
12✔
978
        maxTableIndex := len(q.tables) - 1
12✔
979
        for q.cursor.table < maxTableIndex {
16✔
980
                q.cursor.table++
4✔
981
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
982
                if table.Len() == 0 {
5✔
983
                        continue
1✔
984
                }
985
                if !table.Matches(q.relations) {
3✔
UNCOV
986
                        continue
×
987
                }
988
                q.setTable(q.cursor.table, table)
3✔
989
                return true
3✔
990
        }
991
        return false
9✔
992
}
993

994
func (q *Query6[A, B, C, D, E, F]) setTable(index int, table *table) {
10✔
995
        q.cursor.table = index
10✔
996
        q.table = table
10✔
997
        q.columnA = q.components[0].columns[q.table.id]
10✔
998
        q.columnB = q.components[1].columns[q.table.id]
10✔
999
        q.columnC = q.components[2].columns[q.table.id]
10✔
1000
        q.columnD = q.components[3].columns[q.table.id]
10✔
1001
        q.columnE = q.components[4].columns[q.table.id]
10✔
1002
        q.columnF = q.components[5].columns[q.table.id]
10✔
1003
        q.cursor.index = 0
10✔
1004
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1005
}
10✔
1006

1007
// Query7 is a query for 7 components.
1008
// Use a [NewFilter7] to create one.
1009
type Query7[A any, B any, C any, D any, E any, F any, G any] struct {
1010
        world      *World
1011
        filter     Filter
1012
        relations  []RelationID
1013
        lock       uint8
1014
        cursor     cursor
1015
        tables     []tableID
1016
        table      *table
1017
        components []*componentStorage
1018
        columnA    *column
1019
        columnB    *column
1020
        columnC    *column
1021
        columnD    *column
1022
        columnE    *column
1023
        columnF    *column
1024
        columnG    *column
1025
        hasWithout bool
1026
}
1027

1028
func newQuery7[A any, B any, C any, D any, E any, F any, G any](world *World, filter Filter, ids []ID, relations []RelationID) Query7[A, B, C, D, E, F, G] {
9✔
1029
        components := make([]*componentStorage, 7)
9✔
1030
        for i := range 7 {
72✔
1031
                components[i] = &world.storage.components[ids[i].id]
63✔
1032
        }
63✔
1033

1034
        return Query7[A, B, C, D, E, F, G]{
9✔
1035
                world:      world,
9✔
1036
                filter:     filter,
9✔
1037
                relations:  relations,
9✔
1038
                lock:       world.lock(),
9✔
1039
                components: components,
9✔
1040
                cursor: cursor{
9✔
1041
                        archetype: -1,
9✔
1042
                        table:     -1,
9✔
1043
                        index:     0,
9✔
1044
                        maxIndex:  -1,
9✔
1045
                },
9✔
1046
        }
9✔
1047
}
1048

1049
// Next advances the query's cursor to the next entity.
1050
func (q *Query7[A, B, C, D, E, F, G]) Next() bool {
162✔
1051
        q.world.checkQueryNext(&q.cursor)
162✔
1052
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
1053
                q.cursor.index++
142✔
1054
                return true
142✔
1055
        }
142✔
1056
        return q.nextTableOrArchetype()
20✔
1057
}
1058

1059
// Entity returns the current entity.
1060
func (q *Query7[A, B, C, D, E, F, G]) Entity() Entity {
154✔
1061
        q.world.checkQueryGet(&q.cursor)
154✔
1062
        return q.table.GetEntity(q.cursor.index)
154✔
1063
}
154✔
1064

1065
// Get returns the queried components of the current entity.
1066
func (q *Query7[A, B, C, D, E, F, G]) Get() (*A, *B, *C, *D, *E, *F, *G) {
154✔
1067
        q.world.checkQueryGet(&q.cursor)
154✔
1068
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
1069
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
1070
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
1071
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
1072
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
1073
                (*F)(q.columnF.Get(q.cursor.index)),
154✔
1074
                (*G)(q.columnG.Get(q.cursor.index))
154✔
1075
}
154✔
1076

1077
// GetRelation returns the entity relation target of the component at the given index.
1078
func (q *Query7[A, B, C, D, E, F, G]) GetRelation(index int) Entity {
10✔
1079
        return q.components[index].columns[q.table.id].target
10✔
1080
}
10✔
1081

1082
// Close closes the Query and unlocks the world.
1083
//
1084
// Automatically called when iteration finishes.
1085
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1086
func (q *Query7[A, B, C, D, E, F, G]) Close() {
9✔
1087
        q.cursor.archetype = -2
9✔
1088
        q.cursor.table = -2
9✔
1089
        q.tables = nil
9✔
1090
        q.table = nil
9✔
1091
        q.columnA = nil
9✔
1092
        q.columnB = nil
9✔
1093
        q.columnC = nil
9✔
1094
        q.columnD = nil
9✔
1095
        q.columnE = nil
9✔
1096
        q.columnF = nil
9✔
1097
        q.columnG = nil
9✔
1098
        q.world.unlock(q.lock)
9✔
1099
}
9✔
1100

1101
func (q *Query7[A, B, C, D, E, F, G]) nextTableOrArchetype() bool {
20✔
1102
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
1103
                return true
1✔
1104
        }
1✔
1105
        return q.nextArchetype()
19✔
1106
}
1107

1108
func (q *Query7[A, B, C, D, E, F, G]) nextArchetype() bool {
19✔
1109
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
1110
        for q.cursor.archetype < maxArchIndex {
46✔
1111
                q.cursor.archetype++
27✔
1112
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
1113
                if !q.filter.matches(&archetype.mask) {
44✔
1114
                        continue
17✔
1115
                }
1116

1117
                if !archetype.HasRelations() {
16✔
1118
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1119
                        if table.Len() > 0 {
14✔
1120
                                q.setTable(0, table)
7✔
1121
                                return true
7✔
1122
                        }
7✔
UNCOV
1123
                        continue
×
1124
                }
1125

1126
                q.tables = archetype.GetTables(q.relations)
2✔
1127
                q.cursor.table = -1
2✔
1128
                if q.nextTable() {
4✔
1129
                        return true
2✔
1130
                }
2✔
1131
        }
1132
        q.Close()
9✔
1133
        return false
9✔
1134
}
1135

1136
func (q *Query7[A, B, C, D, E, F, G]) nextTable() bool {
12✔
1137
        maxTableIndex := len(q.tables) - 1
12✔
1138
        for q.cursor.table < maxTableIndex {
16✔
1139
                q.cursor.table++
4✔
1140
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
1141
                if table.Len() == 0 {
5✔
1142
                        continue
1✔
1143
                }
1144
                if !table.Matches(q.relations) {
3✔
UNCOV
1145
                        continue
×
1146
                }
1147
                q.setTable(q.cursor.table, table)
3✔
1148
                return true
3✔
1149
        }
1150
        return false
9✔
1151
}
1152

1153
func (q *Query7[A, B, C, D, E, F, G]) setTable(index int, table *table) {
10✔
1154
        q.cursor.table = index
10✔
1155
        q.table = table
10✔
1156
        q.columnA = q.components[0].columns[q.table.id]
10✔
1157
        q.columnB = q.components[1].columns[q.table.id]
10✔
1158
        q.columnC = q.components[2].columns[q.table.id]
10✔
1159
        q.columnD = q.components[3].columns[q.table.id]
10✔
1160
        q.columnE = q.components[4].columns[q.table.id]
10✔
1161
        q.columnF = q.components[5].columns[q.table.id]
10✔
1162
        q.columnG = q.components[6].columns[q.table.id]
10✔
1163
        q.cursor.index = 0
10✔
1164
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1165
}
10✔
1166

1167
// Query8 is a query for 8 components.
1168
// Use a [NewFilter8] to create one.
1169
type Query8[A any, B any, C any, D any, E any, F any, G any, H any] struct {
1170
        world      *World
1171
        filter     Filter
1172
        relations  []RelationID
1173
        lock       uint8
1174
        cursor     cursor
1175
        tables     []tableID
1176
        table      *table
1177
        components []*componentStorage
1178
        columnA    *column
1179
        columnB    *column
1180
        columnC    *column
1181
        columnD    *column
1182
        columnE    *column
1183
        columnF    *column
1184
        columnG    *column
1185
        columnH    *column
1186
        hasWithout bool
1187
}
1188

1189
func newQuery8[A any, B any, C any, D any, E any, F any, G any, H any](world *World, filter Filter, ids []ID, relations []RelationID) Query8[A, B, C, D, E, F, G, H] {
9✔
1190
        components := make([]*componentStorage, 8)
9✔
1191
        for i := range 8 {
81✔
1192
                components[i] = &world.storage.components[ids[i].id]
72✔
1193
        }
72✔
1194

1195
        return Query8[A, B, C, D, E, F, G, H]{
9✔
1196
                world:      world,
9✔
1197
                filter:     filter,
9✔
1198
                relations:  relations,
9✔
1199
                lock:       world.lock(),
9✔
1200
                components: components,
9✔
1201
                cursor: cursor{
9✔
1202
                        archetype: -1,
9✔
1203
                        table:     -1,
9✔
1204
                        index:     0,
9✔
1205
                        maxIndex:  -1,
9✔
1206
                },
9✔
1207
        }
9✔
1208
}
1209

1210
// Next advances the query's cursor to the next entity.
1211
func (q *Query8[A, B, C, D, E, F, G, H]) Next() bool {
162✔
1212
        q.world.checkQueryNext(&q.cursor)
162✔
1213
        if int64(q.cursor.index) < q.cursor.maxIndex {
304✔
1214
                q.cursor.index++
142✔
1215
                return true
142✔
1216
        }
142✔
1217
        return q.nextTableOrArchetype()
20✔
1218
}
1219

1220
// Entity returns the current entity.
1221
func (q *Query8[A, B, C, D, E, F, G, H]) Entity() Entity {
154✔
1222
        q.world.checkQueryGet(&q.cursor)
154✔
1223
        return q.table.GetEntity(q.cursor.index)
154✔
1224
}
154✔
1225

1226
// Get returns the queried components of the current entity.
1227
func (q *Query8[A, B, C, D, E, F, G, H]) Get() (*A, *B, *C, *D, *E, *F, *G, *H) {
154✔
1228
        q.world.checkQueryGet(&q.cursor)
154✔
1229
        return (*A)(q.columnA.Get(q.cursor.index)),
154✔
1230
                (*B)(q.columnB.Get(q.cursor.index)),
154✔
1231
                (*C)(q.columnC.Get(q.cursor.index)),
154✔
1232
                (*D)(q.columnD.Get(q.cursor.index)),
154✔
1233
                (*E)(q.columnE.Get(q.cursor.index)),
154✔
1234
                (*F)(q.columnF.Get(q.cursor.index)),
154✔
1235
                (*G)(q.columnG.Get(q.cursor.index)),
154✔
1236
                (*H)(q.columnH.Get(q.cursor.index))
154✔
1237
}
154✔
1238

1239
// GetRelation returns the entity relation target of the component at the given index.
1240
func (q *Query8[A, B, C, D, E, F, G, H]) GetRelation(index int) Entity {
10✔
1241
        return q.components[index].columns[q.table.id].target
10✔
1242
}
10✔
1243

1244
// Close closes the Query and unlocks the world.
1245
//
1246
// Automatically called when iteration finishes.
1247
// Needs to be called only if breaking out of the query iteration or not iterating at all.
1248
func (q *Query8[A, B, C, D, E, F, G, H]) Close() {
9✔
1249
        q.cursor.archetype = -2
9✔
1250
        q.cursor.table = -2
9✔
1251
        q.tables = nil
9✔
1252
        q.table = nil
9✔
1253
        q.columnA = nil
9✔
1254
        q.columnB = nil
9✔
1255
        q.columnC = nil
9✔
1256
        q.columnD = nil
9✔
1257
        q.columnE = nil
9✔
1258
        q.columnF = nil
9✔
1259
        q.columnG = nil
9✔
1260
        q.columnH = nil
9✔
1261
        q.world.unlock(q.lock)
9✔
1262
}
9✔
1263

1264
func (q *Query8[A, B, C, D, E, F, G, H]) nextTableOrArchetype() bool {
20✔
1265
        if q.cursor.archetype >= 0 && q.nextTable() {
21✔
1266
                return true
1✔
1267
        }
1✔
1268
        return q.nextArchetype()
19✔
1269
}
1270

1271
func (q *Query8[A, B, C, D, E, F, G, H]) nextArchetype() bool {
19✔
1272
        maxArchIndex := len(q.world.storage.archetypes) - 1
19✔
1273
        for q.cursor.archetype < maxArchIndex {
46✔
1274
                q.cursor.archetype++
27✔
1275
                archetype := &q.world.storage.archetypes[q.cursor.archetype]
27✔
1276
                if !q.filter.matches(&archetype.mask) {
44✔
1277
                        continue
17✔
1278
                }
1279

1280
                if !archetype.HasRelations() {
16✔
1281
                        table := &q.world.storage.tables[archetype.tables[0]]
7✔
1282
                        if table.Len() > 0 {
14✔
1283
                                q.setTable(0, table)
7✔
1284
                                return true
7✔
1285
                        }
7✔
UNCOV
1286
                        continue
×
1287
                }
1288

1289
                q.tables = archetype.GetTables(q.relations)
2✔
1290
                q.cursor.table = -1
2✔
1291
                if q.nextTable() {
4✔
1292
                        return true
2✔
1293
                }
2✔
1294
        }
1295
        q.Close()
9✔
1296
        return false
9✔
1297
}
1298

1299
func (q *Query8[A, B, C, D, E, F, G, H]) nextTable() bool {
12✔
1300
        maxTableIndex := len(q.tables) - 1
12✔
1301
        for q.cursor.table < maxTableIndex {
16✔
1302
                q.cursor.table++
4✔
1303
                table := &q.world.storage.tables[q.tables[q.cursor.table]]
4✔
1304
                if table.Len() == 0 {
5✔
1305
                        continue
1✔
1306
                }
1307
                if !table.Matches(q.relations) {
3✔
UNCOV
1308
                        continue
×
1309
                }
1310
                q.setTable(q.cursor.table, table)
3✔
1311
                return true
3✔
1312
        }
1313
        return false
9✔
1314
}
1315

1316
func (q *Query8[A, B, C, D, E, F, G, H]) setTable(index int, table *table) {
10✔
1317
        q.cursor.table = index
10✔
1318
        q.table = table
10✔
1319
        q.columnA = q.components[0].columns[q.table.id]
10✔
1320
        q.columnB = q.components[1].columns[q.table.id]
10✔
1321
        q.columnC = q.components[2].columns[q.table.id]
10✔
1322
        q.columnD = q.components[3].columns[q.table.id]
10✔
1323
        q.columnE = q.components[4].columns[q.table.id]
10✔
1324
        q.columnF = q.components[5].columns[q.table.id]
10✔
1325
        q.columnG = q.components[6].columns[q.table.id]
10✔
1326
        q.columnH = q.components[7].columns[q.table.id]
10✔
1327
        q.cursor.index = 0
10✔
1328
        q.cursor.maxIndex = int64(q.table.entities.Len() - 1)
10✔
1329
}
10✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc