1use core::marker::PhantomData;
2
3use crate::query::{Fetch, With, Without};
4use crate::{Archetype, Component, Query, QueryItem};
5
6pub struct QueryOne<'a, Q: Query> {
8 archetype: &'a Archetype,
9 index: u32,
10 borrowed: bool,
11 _marker: PhantomData<Q>,
12}
13
14impl<'a, Q: Query> QueryOne<'a, Q> {
15 pub(crate) unsafe fn new(archetype: &'a Archetype, index: u32) -> Self {
21 Self {
22 archetype,
23 index,
24 borrowed: false,
25 _marker: PhantomData,
26 }
27 }
28
29 pub fn get(&mut self) -> Option<QueryItem<'_, Q>> {
37 if self.borrowed {
38 panic!("called QueryOnce::get twice; construct a new query instead");
39 }
40 unsafe {
41 let state = Q::Fetch::prepare(self.archetype)?;
42 Q::Fetch::borrow(self.archetype, state);
43 let fetch = Q::Fetch::execute(self.archetype, state);
44 self.borrowed = true;
45 Some(fetch.get(self.index as usize))
46 }
47 }
48
49 pub fn with<T: Component>(self) -> QueryOne<'a, With<T, Q>> {
53 self.transform()
54 }
55
56 pub fn without<T: Component>(self) -> QueryOne<'a, Without<T, Q>> {
60 self.transform()
61 }
62
63 fn transform<R: Query>(mut self) -> QueryOne<'a, R> {
65 let x = QueryOne {
66 archetype: self.archetype,
67 index: self.index,
68 borrowed: self.borrowed,
69 _marker: PhantomData,
70 };
71 self.borrowed = false;
73 x
74 }
75}
76
77impl<Q: Query> Drop for QueryOne<'_, Q> {
78 fn drop(&mut self) {
79 if self.borrowed {
80 let state = Q::Fetch::prepare(self.archetype).unwrap();
81 Q::Fetch::release(self.archetype, state);
82 }
83 }
84}
85
86unsafe impl<Q: Query> Send for QueryOne<'_, Q> {}
87unsafe impl<Q: Query> Sync for QueryOne<'_, Q> {}