1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
//! Utilities for managing and querying multi-properties.
//!
//! A multi-property is a derived property composed of a tuple of other properties. They are
//! primarily used to enable joint indexing and efficient multi-column style queries.
//!
//! ## Indexing and Normalization
//!
//! To ensure that queries can efficiently find matching indexes, multi-properties that consist
//! of the same set of component properties are considered equivalent, regardless of their
//! definition order. The system achieves this by:
//! 1. **Canonicalization**: Component properties are sorted alphabetically by property name.
//! 2. **Shared Indexes**: The index subsystem reuses a single `Index` instance for all
//! multi-properties that are equivalent up to reordering.
//!
//! ## Query Integration
//!
//! The querying subsystem uses the utilities in this module to detect when a query involving
//! multiple individual properties can be satisfied by an existing multi-property index. If a
//! match is found, the query can perform a fast index lookup instead of iterating over component
//! properties.
//!
//! ## Implementation Details
//!
//! Multi-properties are defined using the [`define_multi_property!`](crate::define_multi_property) macro, which
//! handles the registration and mapping between the property set and its canonical
//! index ID. This module provides the runtime registry (`MULTI_PROPERTY_INDEX_MAP`)
//! and reordering logic used by both the macro-generated code and the query engine.
use TypeId;
use RefCell;
use ;
use crate;
/// A map from a list of `TypeId`s to the index ID of the equivalent multi-property
/// type. The list of `TypeId`s is assumed to be sorted.
///
/// Use `register_type_ids_to_multi_property_index()` to register a multi-property.
/// We could instead just rely on `TypeId::of::<P::CanonicalValue>()`, but this
/// allows us to determine the type dynamically, e.g. for the web API or debug
/// console.
static MULTI_PROPERTY_INDEX_MAP: =
new;
/// A method that looks up the index ID of the multi-property that has the given
/// list of `TypeId`s as its properties.
/// A method that registers the index ID of the multi-property tuple type that has the given
/// list of `TypeId`s as its properties.
///
/// Use `type_ids_to_muli_property_index()` to look up an index ID.
// The following free functions are utilities used to normalize query parts into the same order as
// an equivalent multi-property canonical value. Query tuple impls have to do this dynamically,
// because they do not (and cannot) have a proc-macro-generated trait impl.
/// An iota function that returns an array of the form `[0, 1, 2, 3, ..., N-1]`. The size of the array
/// is statically known, avoiding `Vec` allocations.
const
/// Returns the indices of `keys` in sorted order. These indices are used to reorder some other
/// array according to the sorted order of the `keys`, e.g. by `static_apply_reordering`.
///
/// "Static" in the name refers to the fact that it takes and returns an array of statically
/// known size, avoiding `Vec` allocations.
/// Reorders the `values` in place according to the ordering defined by `indices`. The `indices`
/// is an ordering produced by `sorted_indices`/`static_sorted_indices` and encodes the sorted
/// order of the `keys` (the names of the tag types).
///
/// "Static" in the name refers to the fact that it takes and returns an array of statically
/// known size, avoiding `Vec` allocations.
/// Reorder `values` in place according to the sorted order of `keys`.
///
/// Both slices must have the same length. "Static" in the name refers to the fact that it
/// takes and returns an array of statically known size, avoiding `Vec` allocations.