Skip to main content

unlit_ecs/query/
mod.rs

1//! Queries: picking entities by the components they carry.
2//!
3//! A query is a type, not a value. The components to hand out are written in the
4//! turbofish, so the compiler checks them, and the iterator resolves them once
5//! per archetype instead of once per row.
6//!
7//! | Item | Yields |
8//! | --- | --- |
9//! | `&T` | the component, shared; only archetypes carrying it match |
10//! | `&mut T` | the component, exclusive; only archetypes carrying it match |
11//! | `Option<&T>` | `Some` when the archetype carries the component |
12//! | `Option<&mut T>` | `Some` when it carries it, exclusive |
13//! | `Entity` | the entity itself |
14//! | [`Has<T>`] | whether the archetype carries `T`, narrowing nothing |
15//!
16//! A tuple of items asks for all of them at once and yields a tuple of their
17//! items, and tuples nest: `(&a, (&b, &c))` asks for the same three components
18//! as `(&a, &b, &c)` and yields `(&A, (&B, &C))`. An item written `&(a, b)` is
19//! one component whose type is that tuple, not two, and an item outside the
20//! forms above fails to compile.
21//!
22//! A query is held rather than borrowed one row at a time: [`crate::QueryBorrow`]
23//! is what a scope hands out, it claims the components it will reach when it is
24//! built, and the claims are released when it is dropped. Iterating it is
25//! [`crate::QueryBorrow::iter`].
26//!
27//! ```rust
28//! # use unlit_ecs::{Entity, Has, World, bundle};
29//! let mut world = World::new();
30//! world.root_scope_mut().spawn(bundle![1u32, 10.0f32]);
31//! world.root_scope_mut().spawn(bundle![2u32, true]);
32//!
33//! let mut query = world.root_scope().query::<&u32>();
34//! let sum: u32 = query.iter().map(|value| *value).sum();
35//! assert_eq!(sum, 3);
36//!
37//! // The entity, its component, and whether it also carries a `bool`. The
38//! // `Has<bool>` reports the answer without narrowing anything, so both spawns
39//! // above are visited and the one without a `bool` prints `false`.
40//! for (entity, value, has_bool) in world.root_scope().query::<(Entity, &u32, Has<bool>)>().iter() {
41//!     println!("{entity:?} has {value}, and a bool: {has_bool}");
42//! }
43//!
44//! // Tuples nest, so this asks for the same components and yields
45//! // `(&u32, (&f32,))` instead of `(&u32, &f32)`.
46//! for (value, (height,)) in world.root_scope().query::<(&u32, (&f32,))>().iter() {
47//!     let _ = (value, height);
48//! }
49//! ```
50//!
51//! A query visits archetypes in creation order and rows in storage order, so
52//! iteration is deterministic. It skips the rows the scope cannot see and the
53//! tree's two scaffolding entities.
54//!
55//! Narrowing which archetypes a query visits, including by a component set only
56//! known at run time, is [`crate::QueryBorrow::by`].
57//!
58//! # Queries of your own
59//!
60//! A row that carries more than a tuple impl covers, or one whose components are
61//! worth naming, is declared with the [`crate::query!`] macro:
62//!
63//! ```rust
64//! # use unlit_ecs::{Entity, Has, World, bundle, query};
65//! pub struct Health(pub i32);
66//! pub struct Armor(pub i32);
67//! pub struct Mana(pub i32);
68//!
69//! query! {
70//!     /// Everything one combatant is made of.
71//!     pub struct Combatant<'a> {
72//!         pub entity: Entity,
73//!         pub health: &'a mut Health,
74//!         pub armor: &'a Armor,
75//!         /// `None` for a row that carries no mana.
76//!         pub mana: Option<&'a Mana>,
77//!         pub has_armor: Has<Armor>,
78//!     }
79//! }
80//!
81//! let mut world = World::new();
82//! world.root_scope_mut().spawn(bundle![Health(10), Armor(2)]);
83//!
84//! for row in world.root_scope().query::<Combatant>().iter() {
85//!     row.health.0 -= row.armor.0;
86//!     assert!(row.has_armor);
87//!     assert!(row.mana.is_none());
88//! }
89//! ```
90//!
91//! The declaration is one row: the macro derives the item struct and the
92//! [`Query`] impl from it. No `unsafe` is involved on the caller's side, and
93//! the claims the query makes are exactly the fields it declares: a component is
94//! claimed by asking the [`PlanBuilder`] for it, so there is no second list
95//! that could disagree with what the query actually reaches.
96
97use core::any::TypeId;
98use core::cell::UnsafeCell;
99use core::marker::PhantomData;
100
101use crate::archetype::Archetype;
102use crate::borrow::Claims;
103use crate::entity::Entity;
104use crate::world::World;
105
106#[macro_use]
107mod macros;
108mod iter;
109
110pub use iter::QueryIter;
111
112/// Whether a component is reached shared or exclusive.
113///
114/// A query reports it per component while it resolves its plan, so the holder
115/// knows what to claim before anything is handed out.
116#[derive(Clone, Copy, Debug, PartialEq, Eq)]
117pub enum Mode {
118    /// Reached shared.
119    Read,
120    /// Reached exclusive.
121    Write,
122}
123
124impl Mode {
125    /// The verb a conflict message uses for this mode as a requirement.
126    pub(crate) fn verb(self) -> &'static str {
127        match self {
128            Self::Read => "read",
129            Self::Write => "write",
130        }
131    }
132
133    /// How a conflict message describes a claim already held in this mode.
134    pub(crate) fn adverb(self) -> &'static str {
135        match self {
136            Self::Read => "shared",
137            Self::Write => "exclusively",
138        }
139    }
140}
141
142/// One component a query reaches, and how.
143pub(crate) type Ask = (TypeId, &'static str, Mode);
144
145/// A claimed column, shared.
146///
147/// Handed out by [`PlanBuilder::read`] and kept in a query's plan. It is
148/// [`Copy`], because reading a column twice is not a conflict.
149pub struct Col<'w, T: 'static> {
150    cells: &'w [UnsafeCell<T>],
151}
152
153impl<T: 'static> Clone for Col<'_, T> {
154    fn clone(&self) -> Self {
155        *self
156    }
157}
158
159impl<T: 'static> Copy for Col<'_, T> {}
160
161impl<'w, T: 'static> Col<'w, T> {
162    /// The value at `row`.
163    ///
164    /// It lives as long as the claim behind it, so nothing writes the column
165    /// while any item names it.
166    #[inline]
167    pub fn at(&self, row: usize) -> &'w T {
168        let cell = self
169            .cells
170            .get(row)
171            .unwrap_or_else(|| panic!("row {row} is past the end of a claimed column"));
172        // SAFETY: the holder claimed this column shared for 'w, so nothing
173        // writes it while this reference lives, and the row is in bounds.
174        unsafe { &*cell.get() }
175    }
176
177    /// The number of values in the column, one per row of the archetype.
178    #[inline]
179    #[must_use]
180    pub fn len(&self) -> usize {
181        self.cells.len()
182    }
183
184    /// Whether the column holds no value.
185    #[inline]
186    #[must_use]
187    pub fn is_empty(&self) -> bool {
188        self.cells.is_empty()
189    }
190}
191
192/// A claimed column, exclusive.
193///
194/// Handed out by [`PlanBuilder::write`] and kept in a query's plan. Unlike
195/// [`Col`] it is not [`Copy`], and [`ColMut::at`] takes the handle
196/// exclusively: that is what makes one [`Query::read`] hand out at most one
197/// exclusive reference per column, which in turn is why declaring a query needs
198/// no `unsafe`.
199pub struct ColMut<'w, T: 'static> {
200    cells: &'w [UnsafeCell<T>],
201}
202
203impl<'w, T: 'static> ColMut<'w, T> {
204    /// The value at `row`, exclusively.
205    ///
206    /// Taking `&mut self` is the safety argument: the caller can reach the
207    /// same cell twice only by calling this twice, and the first reference is
208    /// still alive then, so the compiler refuses the second call.
209    #[inline]
210    pub fn at(&mut self, row: usize) -> &mut T {
211        let cell = self
212            .cells
213            .get(row)
214            .unwrap_or_else(|| panic!("row {row} is past the end of a claimed column"));
215        // SAFETY: the holder claimed this column exclusively for the plan's
216        // life, and this handle is the only way to the cells, so no other
217        // reference to any row of it exists.
218        unsafe { &mut *cell.get() }
219    }
220
221    /// The number of values in the column, one per row of the archetype.
222    #[inline]
223    #[must_use]
224    pub fn len(&self) -> usize {
225        self.cells.len()
226    }
227
228    /// Whether the column holds no value.
229    #[inline]
230    #[must_use]
231    pub fn is_empty(&self) -> bool {
232        self.cells.is_empty()
233    }
234}
235
236/// What one archetype offers, and what a query asks of it while resolving its
237/// plan.
238///
239/// This is the only way a query reaches a column, so asking for one *is* the
240/// claim: there is no separate list of reached components that could disagree
241/// with what [`Query::read`] actually reads. A duplicate ask that would need
242/// two modes for one type is refused here, before anything is handed out.
243pub struct PlanBuilder<'w> {
244    archetype: &'w Archetype,
245    asked: Vec<Ask>,
246    marker: PhantomData<&'w ()>,
247}
248
249impl<'w> PlanBuilder<'w> {
250    pub(crate) fn new(archetype: &'w Archetype, asked: Vec<Ask>) -> Self {
251        Self {
252            archetype,
253            asked,
254            marker: PhantomData,
255        }
256    }
257
258    /// The asks recorded so far, which is what the holder claims.
259    pub(crate) fn asks(&self) -> &[Ask] {
260        &self.asked
261    }
262
263    /// Recover the buffer, so the next archetype reuses it instead of
264    /// allocating.
265    pub(crate) fn into_asks(self) -> Vec<Ask> {
266        self.asked
267    }
268
269    /// The archetype's column of `T`, shared. `None` when it carries no
270    /// `T`, which is what makes the query skip it.
271    pub fn read<T: 'static>(&mut self) -> Option<Col<'w, T>> {
272        let cells = self.ask::<T>(Mode::Read)?;
273        Some(Col { cells })
274    }
275
276    /// The archetype's column of `T`, exclusive. `None` when it carries no
277    /// `T`.
278    pub fn write<T: 'static>(&mut self) -> Option<ColMut<'w, T>> {
279        let cells = self.ask::<T>(Mode::Write)?;
280        Some(ColMut { cells })
281    }
282
283    /// Whether the archetype carries `T`.
284    ///
285    /// Claims nothing: a yes/no answer cannot alias anything, which is what
286    /// keeps `(&mut T, Has<T>)` legal.
287    #[inline]
288    #[must_use]
289    pub fn has<T: 'static>(&self) -> bool {
290        self.archetype.has::<T>()
291    }
292
293    /// The entities of the archetype, one per row.
294    #[inline]
295    #[must_use]
296    pub fn entities(&self) -> &'w [Entity] {
297        self.archetype.entities()
298    }
299
300    /// Record that the query reaches `T` in `mode`, and resolve its column.
301    ///
302    /// Panics when the same query asks for `T` twice with at least one of the
303    /// asks exclusive: the two would hand out references that cannot coexist.
304    fn ask<T: 'static>(&mut self, mode: Mode) -> Option<&'w [UnsafeCell<T>]> {
305        let type_id = TypeId::of::<T>();
306        for (asked, name, asked_mode) in &self.asked {
307            if *asked == type_id && (*asked_mode == Mode::Write || mode == Mode::Write) {
308                panic!(
309                    "component `{name}` is already borrowed {} by this query, and this {} cannot share it",
310                    asked_mode.adverb(),
311                    mode.verb(),
312                );
313            }
314        }
315        self.asked
316            .push((type_id, core::any::type_name::<T>(), mode));
317        self.archetype.column::<T>().map(|column| column.cells())
318    }
319}
320
321/// What to fetch from every entity a query matches.
322///
323/// The type is the query: it says which components to hand out and which
324/// archetypes to visit. A query is resolved once per archetype into
325/// [`Query::Plan`] and then read once per row, so iterating costs one
326/// component lookup per archetype rather than one per row.
327///
328/// The impls cover the forms listed in the [module documentation](self), and the
329/// [`crate::query!`] macro derives this trait for a row of the caller's own.
330///
331/// Implementing it by hand needs no `unsafe`: the plan is built through a
332/// [`PlanBuilder`], which claims the very columns it hands out.
333#[diagnostic::on_unimplemented(
334    message = "`{Self}` is not a query",
335    label = "a query is `&C`, `&mut C`, `Option<&C>`, `Option<&mut C>`, `Entity`, `Has<C>`, or a tuple of those",
336    note = "`&(a, b)` is one component whose type is the tuple, and `(&a, &b)` is two; a row with named fields is declared with `query!`"
337)]
338pub trait Query {
339    /// What one matched row yields.
340    ///
341    /// It borrows from the holder that yielded it, never from the world, so an
342    /// item cannot outlive the claims behind it.
343    type Item<'a>;
344
345    /// What is resolved once per archetype and then read once per row.
346    ///
347    /// It borrows from the world, so it may keep the columns of the archetype.
348    /// A row is read through `&mut` of it, which is what keeps the exclusive
349    /// references of one read from aliasing those of the next.
350    type Plan<'w>;
351
352    /// Resolve the plan for one archetype.
353    ///
354    /// `None` means the archetype does not match, and the query skips it.
355    /// Asking the builder for a column the archetype lacks is how a required
356    /// component narrows the query: `builder.read::<T>()?`.
357    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>>;
358
359    /// Read the row at `row` through the resolved plan.
360    ///
361    /// The plan is taken exclusively, so one call reaches at most one exclusive
362    /// reference per column.
363    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a>;
364}
365
366/// Asks for `T` shared.
367impl<T: 'static> Query for &T {
368    type Item<'a> = &'a T;
369    type Plan<'w> = Col<'w, T>;
370
371    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
372        builder.read::<T>()
373    }
374
375    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a> {
376        plan.at(row)
377    }
378}
379
380/// Asks for `T` exclusive.
381impl<T: 'static> Query for &mut T {
382    type Item<'a> = &'a mut T;
383    type Plan<'w> = ColMut<'w, T>;
384
385    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
386        builder.write::<T>()
387    }
388
389    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a> {
390        plan.at(row)
391    }
392}
393
394/// Asks for `T` shared when the archetype carries it.
395impl<T: 'static> Query for Option<&T> {
396    type Item<'a> = Option<&'a T>;
397    type Plan<'w> = Option<Col<'w, T>>;
398
399    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
400        Some(builder.read::<T>())
401    }
402
403    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a> {
404        plan.as_ref().map(|column| column.at(row))
405    }
406}
407
408/// Asks for `T` exclusive when the archetype carries it.
409impl<T: 'static> Query for Option<&mut T> {
410    type Item<'a> = Option<&'a mut T>;
411    type Plan<'w> = Option<ColMut<'w, T>>;
412
413    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
414        Some(builder.write::<T>())
415    }
416
417    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a> {
418        plan.as_mut().map(|column| column.at(row))
419    }
420}
421
422/// Asks for the entity itself.
423///
424/// It is an item like any other, so it can be written first, last, or on its
425/// own: a query over `Entity` alone yields every entity the scope sees.
426impl Query for Entity {
427    type Item<'a> = Entity;
428    type Plan<'w> = &'w [Entity];
429
430    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
431        Some(builder.entities())
432    }
433
434    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a> {
435        plan[row]
436    }
437}
438
439/// Yields whether the archetype carries `T`.
440///
441/// The answer is read from the archetype's component set, so it reaches no value
442/// and never conflicts: `(&mut T, Has<T>)` is legal. Use it instead of
443/// `Option<&T>::is_some()` to ask about a component without borrowing it.
444///
445/// It narrows nothing: every archetype matches, and a row whose archetype lacks
446/// `T` yields `false`. That is what lets a query report presence for rows it
447/// was going to visit anyway, and what keeps `query_one::<Has<T>>` answering
448/// `Ok(false)` rather than an error for an entity that lacks `T`. To visit
449/// only the archetypes carrying `T`, pair it with
450/// [`crate::QueryBorrow::by`]: `.by(|archetype: &Archetype| archetype.has::<T>())`.
451#[derive(Clone, Copy, Debug)]
452pub struct Has<T>(PhantomData<fn() -> T>);
453
454impl<T: 'static> Query for Has<T> {
455    type Item<'a> = bool;
456    type Plan<'w> = bool;
457
458    fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
459        Some(builder.has::<T>())
460    }
461
462    fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, _: usize) -> Self::Item<'a> {
463        *plan
464    }
465}
466
467macro_rules! impl_tuple {
468    ($($name:ident),+) => {
469        /// Asks for every member, yielding a tuple of their items.
470        impl<$($name: Query),+> Query for ($($name,)+) {
471            type Item<'a> = ($($name::Item<'a>,)+);
472            type Plan<'w> = ($($name::Plan<'w>,)+);
473
474            fn prepare<'w>(builder: &mut PlanBuilder<'w>) -> Option<Self::Plan<'w>> {
475                Some(($($name::prepare(builder)?,)+))
476            }
477
478            fn read<'a, 'w: 'a>(plan: &'a mut Self::Plan<'w>, row: usize) -> Self::Item<'a> {
479                #[expect(non_snake_case, reason = "the pattern binds one variable per tuple member")]
480                let ($($name,)+) = plan;
481                ($($name::read($name, row),)+)
482            }
483        }
484    };
485}
486
487impl_tuple!(Q0);
488impl_tuple!(Q0, Q1);
489impl_tuple!(Q0, Q1, Q2);
490impl_tuple!(Q0, Q1, Q2, Q3);
491impl_tuple!(Q0, Q1, Q2, Q3, Q4);
492impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5);
493impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6);
494impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7);
495impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8);
496impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9);
497impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10);
498impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11);
499impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12);
500impl_tuple!(Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13);
501impl_tuple!(
502    Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14
503);
504impl_tuple!(
505    Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15
506);
507
508/// Narrows the archetypes a query visits.
509///
510/// An unadorned query accepts every archetype its items match.
511/// [`crate::QueryBorrow::by`] installs a filter.
512///
513/// A filter is answered from the archetype alone, before any row is fetched and
514/// before any value is reached. Deciding there rather than skipping rows in the
515/// loop is both faster -- a rejected archetype costs one test instead of one per
516/// row -- and correct when the rows it rejects carry a component the caller
517/// reaches exclusively.
518///
519/// Implemented for `()`, which accepts everything, and for any
520/// `Fn(&Archetype) -> bool`. A closure can decide from anything an archetype
521/// knows, including a component set only known at run time, which a type-written
522/// query cannot name.
523///
524/// ```rust
525/// # use unlit_ecs::{Archetype, World, bundle};
526/// let mut world = World::new();
527/// world.root_scope_mut().spawn(bundle![1u32, true]);
528/// world.root_scope_mut().spawn(bundle![2u32]);
529///
530/// let mut query = world
531///     .root_scope()
532///     .query::<&u32>()
533///     .by(|archetype: &Archetype| !archetype.has::<bool>());
534/// let sum: u32 = query.iter().map(|value| *value).sum();
535/// assert_eq!(sum, 2);
536/// ```
537pub trait ArchetypeFilter {
538    /// Whether entities of `archetype` belong to this query.
539    fn accept(&self, archetype: &Archetype) -> bool;
540}
541
542impl ArchetypeFilter for () {
543    fn accept(&self, _: &Archetype) -> bool {
544        true
545    }
546}
547
548impl<F: Fn(&Archetype) -> bool> ArchetypeFilter for F {
549    fn accept(&self, archetype: &Archetype) -> bool {
550        self(archetype)
551    }
552}
553
554/// What a scope hands out for a query: the claims, and the way to iterate them.
555///
556/// The holder is created by [`crate::Scope::query`] and claims the components
557/// the query reaches, archetype by archetype, before it hands out anything.
558/// Iterating is [`QueryBorrow::iter`], and every item it yields borrows from
559/// this holder, so the claims outlive the items by construction.
560///
561/// Dropping the holder releases the claims. Forgetting it instead
562/// ([`core::mem::forget`]) leaks them: the components stay claimed for the rest
563/// of the world's life, and the next query for them panics rather than running
564/// alongside.
565pub struct QueryBorrow<'w, Q: Query, F: ArchetypeFilter = ()> {
566    world: &'w World,
567    scope: Entity,
568    filter: F,
569    claims: Claims<'w>,
570    /// The buffer a pass over the archetypes records its asks in, kept here so
571    /// that a second pass reuses it rather than allocating again.
572    asks: Vec<Ask>,
573    origin: &'static core::panic::Location<'static>,
574    marker: PhantomData<fn() -> Q>,
575}
576
577impl<'w, Q: Query> QueryBorrow<'w, Q, ()> {
578    pub(crate) fn new(
579        world: &'w World,
580        scope: Entity,
581        origin: &'static core::panic::Location<'static>,
582    ) -> Self {
583        Self {
584            world,
585            scope,
586            filter: (),
587            claims: Claims::new(world),
588            asks: Vec::new(),
589            origin,
590            marker: PhantomData,
591        }
592    }
593}
594
595impl<'w, Q: Query, F: ArchetypeFilter> QueryBorrow<'w, Q, F> {
596    /// Visit only the archetypes the filter accepts.
597    ///
598    /// The filter sees an archetype before any of its rows is fetched and before
599    /// any value is reached, so rejecting an archetype costs one test rather than
600    /// one per row, and works even when that archetype's components are already
601    /// claimed elsewhere. See [`ArchetypeFilter`].
602    ///
603    /// It may be applied part-way through an iteration, and then narrows the
604    /// archetype being visited too: what the filter rejects is not fetched, and
605    /// the rows already yielded stay yielded.
606    #[must_use]
607    pub fn by<G: ArchetypeFilter>(self, filter: G) -> QueryBorrow<'w, Q, G> {
608        QueryBorrow {
609            world: self.world,
610            scope: self.scope,
611            filter,
612            claims: self.claims,
613            asks: self.asks,
614            origin: self.origin,
615            marker: PhantomData,
616        }
617    }
618
619    /// Iterate the visible entities that match `Q`.
620    ///
621    /// The items borrow from this holder, so they cannot outlive it and it
622    /// cannot be iterated for one item at a time while another is alive: collect
623    /// them, or finish with each row before reaching for the next.
624    pub fn iter(&mut self) -> QueryIter<'_, 'w, Q> {
625        QueryIter::new(
626            self.world,
627            self.scope,
628            &self.filter,
629            &mut self.claims,
630            &mut self.asks,
631            self.origin,
632        )
633    }
634}
635
636/// What a scope hands out for a query over one entity.
637///
638/// Made by [`crate::Scope::query_one`], which claims the components the query
639/// reaches on that entity's row. A missing match is still answered with an
640/// error rather than a holder, so a caller that finds nothing holds no claim.
641///
642/// [`QueryOne::get`] is what reads the row, and it takes the holder
643/// exclusively: an exclusive item borrows from the call, so the compiler refuses
644/// a second one while the first is alive.
645pub struct QueryOne<'w, Q: Query> {
646    row: usize,
647    plan: Q::Plan<'w>,
648    /// Held for the life of the holder: dropping it is what releases the claim.
649    _claims: Claims<'w>,
650    marker: PhantomData<fn() -> Q>,
651}
652
653impl<'w, Q: Query> QueryOne<'w, Q> {
654    pub(crate) fn new(plan: Q::Plan<'w>, row: usize, claims: Claims<'w>) -> Self {
655        Self {
656            row,
657            plan,
658            _claims: claims,
659            marker: PhantomData,
660        }
661    }
662
663    /// What the query yields for this entity's row.
664    pub fn get(&mut self) -> Q::Item<'_> {
665        Q::read(&mut self.plan, self.row)
666    }
667}
668
669impl<Q: Query> core::fmt::Debug for QueryOne<'_, Q> {
670    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
671        f.debug_struct("QueryOne")
672            .field("row", &self.row)
673            .finish_non_exhaustive()
674    }
675}
676
677impl<Q: Query, F: ArchetypeFilter> core::fmt::Debug for QueryBorrow<'_, Q, F> {
678    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
679        f.debug_struct("QueryBorrow")
680            .field("scope", &self.scope)
681            .finish_non_exhaustive()
682    }
683}