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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
use crate::{
component::ComponentValue,
filter::{Cmp, Equal, Filtered, Greater, GreaterEq, Less, LessEq},
relation::RelationExt,
Fetch, FetchItem,
};
use super::{
as_deref::AsDeref,
cloned::Cloned,
copied::Copied,
opt::{Opt, OptOr},
source::{FetchSource, FromRelation, Traverse},
transform::Added,
Map, Modified, Satisfied, Source, TransformFetch,
};
/// Extension trait for [crate::Fetch]
pub trait FetchExt: Sized {
/// Transform the fetch into an optional fetch, yielding Some or None
fn opt(self) -> Opt<Self> {
Opt { fetch: self }
}
/// Transform the fetch into a fetch with a provided default.
/// This is useful for default values such as scale or velocity which may
/// not exist for every entity.
fn opt_or<V>(self, default: V) -> OptOr<Self, V>
where
Self: for<'w> Fetch<'w>,
for<'q> Self: FetchItem<'q, Item = &'q V>,
{
OptOr::new(self, default)
}
/// Returns true if the query is satisfied, without borrowing
fn satisfied(self) -> Satisfied<Self> {
Satisfied(self)
}
/// Transform the fetch into a fetch which yields the default impl if the
/// fetch is not matched.
fn opt_or_default<V>(self) -> OptOr<Self, V>
where
Self: for<'w> Fetch<'w>,
for<'q> Self: FetchItem<'q, Item = &'q V>,
V: Default,
{
self.opt_or(Default::default())
}
/// Transform this into a cloned fetch
fn cloned(self) -> Cloned<Self>
where
Cloned<Self>: for<'x> Fetch<'x>,
{
Cloned(self)
}
/// Transform this into a copied fetch
fn copied(self) -> Copied<Self>
where
Copied<Self>: for<'x> Fetch<'x>,
{
Copied(self)
}
/// Dereferences the fetch item
fn deref(self) -> AsDeref<Self>
where
AsDeref<Self>: for<'x> Fetch<'x>,
{
AsDeref(self)
}
/// Filter any component by predicate.
fn cmp<F>(self, func: F) -> Cmp<Self, F>
where
for<'x> Cmp<Self, F>: Fetch<'x>,
{
Cmp::new(self, func)
}
/// Filter any component less than `other`.
fn lt<T>(self, other: T) -> Cmp<Self, Less<T>>
where
for<'x> Cmp<Self, Less<T>>: Fetch<'x>,
{
Cmp::new(self, Less(other))
}
/// Filter any component greater than `other`.
fn gt<T>(self, other: T) -> Cmp<Self, Greater<T>>
where
for<'x> Cmp<Self, GreaterEq<T>>: Fetch<'x>,
{
Cmp::new(self, Greater(other))
}
/// Filter any component greater than or equal to `other`.
fn ge<T>(self, other: T) -> Cmp<Self, GreaterEq<T>>
where
for<'x> Cmp<Self, GreaterEq<T>>: Fetch<'x>,
{
Cmp::new(self, GreaterEq(other))
}
/// Filter any component less than or equal to `other`.
fn le<T>(self, other: T) -> Cmp<Self, LessEq<T>>
where
for<'x> Cmp<Self, LessEq<T>>: Fetch<'x>,
{
Cmp::new(self, LessEq(other))
}
/// Filter any component equal to `other`.
fn eq<T>(self, other: T) -> Cmp<Self, Equal<T>>
where
for<'x> Cmp<Self, Equal<T>>: Fetch<'x>,
{
Cmp::new(self, Equal(other))
}
/// Set the source entity for the fetch.
///
/// This allows fetching or joining queries
fn source<S>(self, source: S) -> Source<Self, S>
where
S: FetchSource,
{
Source::new(self, source)
}
/// Follows a relation to resolve the fetch.
///
/// This allows you to for example fetch from the parent of an entity.
fn relation<T, R>(self, relation: R) -> Source<Self, FromRelation>
where
R: RelationExt<T>,
T: ComponentValue,
{
Source::new(
self,
FromRelation {
relation: relation.id(),
name: relation.vtable().name,
},
)
}
/// Traverse the edges of a relation recursively to find the first entity which matches the fetch
///
/// This will attempt to resolve a fetch from and including the source entity, to the roots of the relation.
fn traverse<T, R>(self, relation: R) -> Source<Self, Traverse>
where
R: RelationExt<T>,
T: ComponentValue,
{
Source::new(
self,
Traverse {
relation: relation.id(),
},
)
}
/// Transform the fetch into a fetch where each constituent part tracks and yields for
/// modification events.
///
/// This is different from E.g; `(a().modified(), b().modified())` as it implies only when
/// *both* `a` and `b` are modified in the same iteration, which is seldom useful.
///
/// This means will yield *any* of `a` *or* `b` are modified.
///
/// Works with `opt`, `copy`, etc constituents.
fn modified(self) -> <Self as TransformFetch<Modified>>::Output
where
Self: TransformFetch<Modified>,
{
self.transform_fetch(Modified)
}
/// Transform the fetch into a fetch where each constituent part tracks and yields for
/// component addition events.
///
/// This is different from E.g; `(a().modified(), b().modified())` as it implies only when
/// *both* `a` and `b` are modified in the same iteration, which is seldom useful.
///
/// This means will yield *any* of `a` *or* `b` are modified.
///
/// Works with `opt`, `copy`, etc constituents.
fn added(self) -> <Self as TransformFetch<Added>>::Output
where
Self: TransformFetch<Added>,
{
self.transform_fetch(Added)
}
/// Map each item of the query to another type using the provided function.
fn map<F, T>(self, func: F) -> Map<Self, F>
where
Self: for<'x> FetchItem<'x>,
for<'x> F: Fn(<Self as FetchItem<'x>>::Item) -> T,
{
Map { query: self, func }
}
/// Filter a fetch with another fetch as predicate
fn filtered<F>(self, filter: F) -> Filtered<Self, F>
where
F: for<'x> Fetch<'x>,
{
Filtered::new(self, filter, true)
}
}
impl<F> FetchExt for F where F: for<'x> Fetch<'x> {}