@@ -43,6 +43,7 @@ use std::{
4343pub trait WorldQuery {
4444 type Fetch : for < ' a > Fetch < ' a , State = Self :: State > ;
4545 type State : FetchState ;
46+ type ReadOnlyFetch : for < ' a > Fetch < ' a , State = Self :: State > + ReadOnlyFetch ;
4647}
4748
4849pub trait Fetch < ' w > : Sized {
@@ -134,6 +135,7 @@ pub unsafe trait ReadOnlyFetch {}
134135impl WorldQuery for Entity {
135136 type Fetch = EntityFetch ;
136137 type State = EntityState ;
138+ type ReadOnlyFetch = EntityFetch ;
137139}
138140
139141/// The [`Fetch`] of [`Entity`].
@@ -222,6 +224,7 @@ impl<'w> Fetch<'w> for EntityFetch {
222224impl < T : Component > WorldQuery for & T {
223225 type Fetch = ReadFetch < T > ;
224226 type State = ReadState < T > ;
227+ type ReadOnlyFetch = ReadFetch < T > ;
225228}
226229
227230/// The [`FetchState`] of `&T`.
@@ -382,6 +385,7 @@ impl<'w, T: Component> Fetch<'w> for ReadFetch<T> {
382385impl < T : Component > WorldQuery for & mut T {
383386 type Fetch = WriteFetch < T > ;
384387 type State = WriteState < T > ;
388+ type ReadOnlyFetch = ReadOnlyWriteFetch < T > ;
385389}
386390
387391/// The [`Fetch`] of `&mut T`.
@@ -411,6 +415,36 @@ impl<T> Clone for WriteFetch<T> {
411415 }
412416}
413417
418+ /// The [`ReadOnlyFetch`] of `&mut T`.
419+ pub struct ReadOnlyWriteFetch < T > {
420+ storage_type : StorageType ,
421+ table_components : NonNull < T > ,
422+ table_ticks : * const UnsafeCell < ComponentTicks > ,
423+ entities : * const Entity ,
424+ entity_table_rows : * const usize ,
425+ sparse_set : * const ComponentSparseSet ,
426+ last_change_tick : u32 ,
427+ change_tick : u32 ,
428+ }
429+
430+ /// SAFETY: access is read only
431+ unsafe impl < T > ReadOnlyFetch for ReadOnlyWriteFetch < T > { }
432+
433+ impl < T > Clone for ReadOnlyWriteFetch < T > {
434+ fn clone ( & self ) -> Self {
435+ Self {
436+ storage_type : self . storage_type ,
437+ table_components : self . table_components ,
438+ table_ticks : self . table_ticks ,
439+ entities : self . entities ,
440+ entity_table_rows : self . entity_table_rows ,
441+ sparse_set : self . sparse_set ,
442+ last_change_tick : self . last_change_tick ,
443+ change_tick : self . change_tick ,
444+ }
445+ }
446+ }
447+
414448/// The [`FetchState`] of `&mut T`.
415449pub struct WriteState < T > {
416450 component_id : ComponentId ,
@@ -567,9 +601,95 @@ impl<'w, T: Component> Fetch<'w> for WriteFetch<T> {
567601 }
568602}
569603
604+ impl < ' w , T : Component > Fetch < ' w > for ReadOnlyWriteFetch < T > {
605+ type Item = & ' w T ;
606+ type State = WriteState < T > ;
607+
608+ #[ inline]
609+ fn is_dense ( & self ) -> bool {
610+ match self . storage_type {
611+ StorageType :: Table => true ,
612+ StorageType :: SparseSet => false ,
613+ }
614+ }
615+
616+ unsafe fn init (
617+ world : & World ,
618+ state : & Self :: State ,
619+ last_change_tick : u32 ,
620+ change_tick : u32 ,
621+ ) -> Self {
622+ let mut value = Self {
623+ storage_type : state. storage_type ,
624+ table_components : NonNull :: dangling ( ) ,
625+ entities : ptr:: null :: < Entity > ( ) ,
626+ entity_table_rows : ptr:: null :: < usize > ( ) ,
627+ sparse_set : ptr:: null :: < ComponentSparseSet > ( ) ,
628+ table_ticks : ptr:: null :: < UnsafeCell < ComponentTicks > > ( ) ,
629+ last_change_tick,
630+ change_tick,
631+ } ;
632+ if state. storage_type == StorageType :: SparseSet {
633+ value. sparse_set = world
634+ . storages ( )
635+ . sparse_sets
636+ . get ( state. component_id )
637+ . unwrap ( ) ;
638+ }
639+ value
640+ }
641+
642+ #[ inline]
643+ unsafe fn set_archetype (
644+ & mut self ,
645+ state : & Self :: State ,
646+ archetype : & Archetype ,
647+ tables : & Tables ,
648+ ) {
649+ match state. storage_type {
650+ StorageType :: Table => {
651+ self . entity_table_rows = archetype. entity_table_rows ( ) . as_ptr ( ) ;
652+ let column = tables[ archetype. table_id ( ) ]
653+ . get_column ( state. component_id )
654+ . unwrap ( ) ;
655+ self . table_components = column. get_data_ptr ( ) . cast :: < T > ( ) ;
656+ self . table_ticks = column. get_ticks_ptr ( ) ;
657+ }
658+ StorageType :: SparseSet => self . entities = archetype. entities ( ) . as_ptr ( ) ,
659+ }
660+ }
661+
662+ #[ inline]
663+ unsafe fn set_table ( & mut self , state : & Self :: State , table : & Table ) {
664+ let column = table. get_column ( state. component_id ) . unwrap ( ) ;
665+ self . table_components = column. get_data_ptr ( ) . cast :: < T > ( ) ;
666+ self . table_ticks = column. get_ticks_ptr ( ) ;
667+ }
668+
669+ #[ inline]
670+ unsafe fn archetype_fetch ( & mut self , archetype_index : usize ) -> Self :: Item {
671+ match self . storage_type {
672+ StorageType :: Table => {
673+ let table_row = * self . entity_table_rows . add ( archetype_index) ;
674+ & * self . table_components . as_ptr ( ) . add ( table_row)
675+ }
676+ StorageType :: SparseSet => {
677+ let entity = * self . entities . add ( archetype_index) ;
678+ & * ( * self . sparse_set ) . get ( entity) . unwrap ( ) . cast :: < T > ( )
679+ }
680+ }
681+ }
682+
683+ #[ inline]
684+ unsafe fn table_fetch ( & mut self , table_row : usize ) -> Self :: Item {
685+ & * self . table_components . as_ptr ( ) . add ( table_row)
686+ }
687+ }
688+
570689impl < T : WorldQuery > WorldQuery for Option < T > {
571690 type Fetch = OptionFetch < T :: Fetch > ;
572691 type State = OptionState < T :: State > ;
692+ type ReadOnlyFetch = OptionFetch < T :: ReadOnlyFetch > ;
573693}
574694
575695/// The [`Fetch`] of `Option<T>`.
@@ -745,6 +865,7 @@ impl<T: Component> ChangeTrackers<T> {
745865impl < T : Component > WorldQuery for ChangeTrackers < T > {
746866 type Fetch = ChangeTrackersFetch < T > ;
747867 type State = ChangeTrackersState < T > ;
868+ type ReadOnlyFetch = ChangeTrackersFetch < T > ;
748869}
749870
750871/// The [`FetchState`] of [`ChangeTrackers`].
@@ -987,6 +1108,7 @@ macro_rules! impl_tuple_fetch {
9871108 impl <$( $name: WorldQuery ) ,* > WorldQuery for ( $( $name, ) * ) {
9881109 type Fetch = ( $( $name:: Fetch , ) * ) ;
9891110 type State = ( $( $name:: State , ) * ) ;
1111+ type ReadOnlyFetch = ( $( $name:: ReadOnlyFetch , ) * ) ;
9901112 }
9911113
9921114 /// SAFETY: each item in the tuple is read only
@@ -996,3 +1118,48 @@ macro_rules! impl_tuple_fetch {
9961118}
9971119
9981120all_tuples ! ( impl_tuple_fetch, 0 , 15 , F , S ) ;
1121+
1122+ /// [`Fetch`] that does not actually fetch anything
1123+ ///
1124+ /// Mostly useful when something is generic over the Fetch and you don't want to fetch as you will discard the result
1125+ pub struct NopFetch < State > {
1126+ state : PhantomData < State > ,
1127+ }
1128+
1129+ impl < ' w , State : FetchState > Fetch < ' w > for NopFetch < State > {
1130+ type Item = ( ) ;
1131+ type State = State ;
1132+
1133+ #[ inline( always) ]
1134+ unsafe fn init (
1135+ _world : & World ,
1136+ _state : & Self :: State ,
1137+ _last_change_tick : u32 ,
1138+ _change_tick : u32 ,
1139+ ) -> Self {
1140+ Self { state : PhantomData }
1141+ }
1142+
1143+ #[ inline( always) ]
1144+ fn is_dense ( & self ) -> bool {
1145+ true
1146+ }
1147+
1148+ #[ inline( always) ]
1149+ unsafe fn set_archetype (
1150+ & mut self ,
1151+ _state : & Self :: State ,
1152+ _archetype : & Archetype ,
1153+ _tables : & Tables ,
1154+ ) {
1155+ }
1156+
1157+ #[ inline( always) ]
1158+ unsafe fn set_table ( & mut self , _state : & Self :: State , _table : & Table ) { }
1159+
1160+ #[ inline( always) ]
1161+ unsafe fn archetype_fetch ( & mut self , _archetype_index : usize ) -> Self :: Item { }
1162+
1163+ #[ inline( always) ]
1164+ unsafe fn table_fetch ( & mut self , _table_row : usize ) -> Self :: Item { }
1165+ }
0 commit comments