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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
use super::World;
use crate::component::Component;
impl World {
// ==========================================================
// ERGONOMİK SORGULAR (QUERY API)
// ==========================================================
/// Salt-okunur bir [`Query`](crate::query::Query) oluşturur (paylaşımlı component erişimi).
///
/// `Q: ReadOnlyQuery` bağlı olduğundan bu giriş noktası `&mut T` ÜRETEMEZ — `&self`'ten
/// istenildiği kadar oluşturulabilir, hepsi aynı anda canlı olabilir, hiçbiri UB değildir.
/// Mutable erişim için [`World::query_mut`] (`&mut World` ister; güvenli) veya — paralel
/// scheduler içindeki sistemler için — [`World::query_unchecked`] (`unsafe`) kullanın.
///
/// Bu ayrım, denetimin "tek en zayıf noktası" olan dual-`Mut` aliasing UB'sini **güvenli
/// koddan ULAŞILAMAZ** kılar: `&World`'ten mutable query yalnızca `unsafe` ile alınır.
///
/// # Examples
/// Shared reads compose freely:
/// ```
/// use gizmo_core::prelude::*;
/// #[derive(Clone)]
/// struct Position { x: f32 }
/// gizmo_core::impl_component!(Position);
///
/// let mut world = World::new();
/// world.register_component_type::<Position>();
/// let e = world.spawn();
/// world.add_component(e, Position { x: 1.0 });
///
/// let r1 = world.query::<&Position>().unwrap();
/// let r2 = world.query::<&Position>().unwrap(); // any number may coexist
/// assert_eq!(r1.get(e.id()).unwrap().x, 1.0);
/// assert_eq!(r2.get(e.id()).unwrap().x, 1.0);
/// ```
///
/// A *mutable* query can NOT be built through `query` — `Mut<T>` is not
/// [`ReadOnlyQuery`](crate::query::ReadOnlyQuery), so the dual-`Mut` UB is unreachable
/// from safe code (use [`World::query_mut`] instead):
/// ```compile_fail
/// use gizmo_core::prelude::*;
/// #[derive(Clone)]
/// struct Position { x: f32 }
/// gizmo_core::impl_component!(Position);
///
/// let world = World::new();
/// // error[E0277]: `Mut<Position>: ReadOnlyQuery` is not satisfied
/// let _q = world.query::<Mut<Position>>();
/// ```
pub fn query<'w, Q: crate::query::ReadOnlyQuery>(
&'w self,
) -> Option<crate::query::Query<'w, Q>> {
crate::query::Query::new(self)
}
/// Mutable bir [`Query`](crate::query::Query) oluşturur. `&mut self` aldığından dönen
/// query World'ü ÖZEL olarak ödünç alır → ikinci bir (mutable VEYA okuma) query aynı anda
/// derlenemez. Bu, iki canlı `Mut` query'sinin aynı belleği alias'lamasını tip düzeyinde
/// imkânsız kılan güvenli yoldur.
///
/// World'e özel erişimi olan uygulama kodu (oyun döngüsü, editör, exclusive sistemler)
/// için tercih edilen mutable giriş noktasıdır.
///
/// # Examples
/// ```
/// use gizmo_core::prelude::*;
/// #[derive(Clone)]
/// struct Position { x: f32 }
/// gizmo_core::impl_component!(Position);
///
/// let mut world = World::new();
/// world.register_component_type::<Position>();
/// let e = world.spawn();
/// world.add_component(e, Position { x: 1.0 });
///
/// {
/// let mut q = world.query_mut::<Mut<Position>>().unwrap();
/// for (_id, mut p) in q.iter_mut() { p.x += 1.0; }
/// }
/// assert_eq!(world.query::<&Position>().unwrap().get(e.id()).unwrap().x, 2.0);
/// ```
///
/// Two simultaneous mutable queries can't exist — each ties up `&mut World`, so the
/// dual-`Mut` aliasing is rejected at compile time:
/// ```compile_fail
/// use gizmo_core::prelude::*;
/// #[derive(Clone)]
/// struct Position { x: f32 }
/// gizmo_core::impl_component!(Position);
///
/// let mut world = World::new();
/// let q1 = world.query_mut::<Mut<Position>>();
/// let q2 = world.query_mut::<Mut<Position>>(); // second &mut World — E0499
/// let _ = (q1, q2);
/// ```
///
/// Likewise, two live mutable views from ONE query can't coexist (`get_mut` borrows the
/// query exclusively):
/// ```compile_fail
/// use gizmo_core::prelude::*;
/// #[derive(Clone)]
/// struct Position { x: f32 }
/// gizmo_core::impl_component!(Position);
///
/// let mut world = World::new();
/// world.register_component_type::<Position>();
/// let mut q = world.query_mut::<Mut<Position>>().unwrap();
/// let a = q.get_mut(0);
/// let b = q.get_mut(0); // second &mut borrow of `q` — E0499
/// let _ = (a, b);
/// ```
///
/// The shared accessors (`iter`/`get`/…) are gated to read-only queries, so a mutable
/// query can't hand out an aliasable shared iterator either — use `iter_mut`:
/// ```compile_fail
/// use gizmo_core::prelude::*;
/// #[derive(Clone)]
/// struct Position { x: f32 }
/// gizmo_core::impl_component!(Position);
///
/// let mut world = World::new();
/// let q = world.query_mut::<Mut<Position>>().unwrap();
/// let _it = q.iter(); // `iter` requires `Q: ReadOnlyQuery`; Mut<Position> isn't — E0599
/// ```
pub fn query_mut<'w, Q: crate::query::WorldQuery>(
&'w mut self,
) -> Option<crate::query::Query<'w, Q>> {
crate::query::Query::new(self)
}
/// `&World`'ten mutable bir query oluşturan KAÇIŞ KAPISI. Paralel scheduler içindeki
/// sistemler (`System::run(&World)`) için — onların `&mut World`'ü yoktur ama disjoint
/// erişimleri `AccessInfo`/`is_compatible_with` tarafından zamanlama anında doğrulanır.
///
/// # Safety
/// Çağıran, bu query'nin canlı olduğu süre boyunca, AYNI component'lere mutable dokunan
/// başka HİÇBİR query'nin (bu World üzerinde, bu veya başka bir thread'de) canlı
/// olmamasını GARANTİ etmelidir. Motorda bu garanti şuralardan gelir:
/// - paralel batch'lerde her sistemin `AccessInfo`'su `is_compatible_with` ile
/// çakışmayacak şekilde gruplanır (disjoint component erişimi), ve
/// - `is_exclusive` sistemler tek başına çalışır.
///
/// Bu sözleşme ihlal edilirse iki `&mut T` alias oluşur → tanımsız davranış. Özel erişimin
/// varsa bunun yerine güvenli [`World::query_mut`]'i kullan.
pub unsafe fn query_unchecked<'w, Q: crate::query::WorldQuery>(
&'w self,
) -> Option<crate::query::Query<'w, Q>> {
crate::query::Query::new(self)
}
/// Geriye uyumluluk için StorageView alternatifi (`&T` paylaşımlı erişim — daima sağlam).
#[inline]
pub fn borrow<'w, T: Component>(&'w self) -> crate::query::Query<'w, &'w T> {
self.query::<&T>().expect("Failed to create borrow Query")
}
/// Tek bir component için mutable query (`Mut<T>`) — güvenli, `&mut self` ister.
/// [`World::query_mut`]'in ergonomik kısaltması; aynı tip-düzeyi aliasing güvencesini taşır.
#[inline]
pub fn borrow_mut<'w, T: Component>(
&'w mut self,
) -> crate::query::Query<'w, crate::query::Mut<'w, T>> {
self.query_mut::<crate::query::Mut<T>>().expect("Failed to create borrow_mut Query")
}
/// [`World::borrow_mut`]'in `unsafe` kaçış-kapısı sürümü — `&World`'ten `Mut<T>` query'si
/// kuran paralel-scheduler sistemleri için.
///
/// # Safety
/// [`World::query_unchecked`] ile aynı sözleşme: bu query canlıyken `T`'ye mutable dokunan
/// başka bir query canlı olmamalı (scheduler disjointness'i garanti eder).
#[inline]
pub unsafe fn borrow_mut_unchecked<'w, T: Component>(
&'w self,
) -> crate::query::Query<'w, crate::query::Mut<'w, T>> {
self.query_unchecked::<crate::query::Mut<T>>()
.expect("Failed to create borrow_mut_unchecked Query")
}
/// Cache'li query — archetype indeks cache'ini kullanır.
/// &mut self gerektirdiği için sadece World sahibiyken çağrılabilir.
pub fn query_cached<'w, Q: crate::query::WorldQuery>(
&'w mut self,
) -> Option<crate::query::Query<'w, Q>> {
crate::query::Query::new_cached(self)
}
/// **Ham `u32` id ile — generation kontrolü yapmaz.** Despawn+reuse sonrası yanlış
/// entity'nin verisi dönebilir; canlılık kritikse önce [`World::is_alive`] çağırın.
pub fn query_entity_mut<'w, Q: crate::query::WorldQuery>(
&'w mut self,
entity_id: u32,
) -> Option<Q::Item<'w>> {
let loc = self.entity_location(entity_id);
if !loc.is_valid() {
return None;
}
let arch = &self.archetype_index.archetypes[loc.archetype_id as usize];
if !Q::matches_archetype(arch) {
return None;
}
unsafe {
let fetch = Q::fetch_raw(self, arch, self.tick)?;
if !Q::filter_row(fetch, loc.row as usize, entity_id, self.change_ref_tick) {
return None;
}
Some(Q::get_item(fetch, loc.row as usize, entity_id))
}
}
/// Tek bir entity üzerinde read-only `Query` çalıştırıp anında sonuç almanızı sağlar.
///
/// `Q: ReadOnlyQuery` bağlı (paylaşımlı `&self`'ten mutable sonuç dönemez); mutable tekil
/// erişim için [`World::query_entity_mut`] (`&mut self`).
///
/// **Ham `u32` id ile — generation kontrolü yapmaz** (bkz. [`World::query_entity_mut`]).
pub fn query_entity<'w, Q: crate::query::ReadOnlyQuery>(
&'w self,
entity_id: u32,
) -> Option<Q::Item<'w>> {
let loc = self.entity_location(entity_id);
if !loc.is_valid() {
return None;
}
let arch = &self.archetype_index.archetypes[loc.archetype_id as usize];
if !Q::matches_archetype(arch) {
return None;
}
unsafe {
let fetch = Q::fetch_raw(self, arch, self.tick)?;
if !Q::filter_row(fetch, loc.row as usize, entity_id, self.change_ref_tick) {
return None;
}
Some(Q::get_item(fetch, loc.row as usize, entity_id))
}
}
}