bevy_ecs/world/
filtered_resource.rs

1use crate::{
2    change_detection::{Mut, MutUntyped, Ref, Ticks, TicksMut},
3    component::{ComponentId, Tick},
4    query::Access,
5    resource::Resource,
6    world::{unsafe_world_cell::UnsafeWorldCell, World},
7};
8use bevy_ptr::{Ptr, UnsafeCellDeref};
9
10use super::error::ResourceFetchError;
11
12/// Provides read-only access to a set of [`Resource`]s defined by the contained [`Access`].
13///
14/// Use [`FilteredResourcesMut`] if you need mutable access to some resources.
15///
16/// To be useful as a [`SystemParam`](crate::system::SystemParam),
17/// this must be configured using a [`FilteredResourcesParamBuilder`](crate::system::FilteredResourcesParamBuilder)
18/// to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
19///
20/// # Examples
21///
22/// ```
23/// # use bevy_ecs::{prelude::*, system::*};
24/// #
25/// # #[derive(Default, Resource)]
26/// # struct A;
27/// #
28/// # #[derive(Default, Resource)]
29/// # struct B;
30/// #
31/// # #[derive(Default, Resource)]
32/// # struct C;
33/// #
34/// # let mut world = World::new();
35/// // Use `FilteredResourcesParamBuilder` to declare access to resources.
36/// let system = (FilteredResourcesParamBuilder::new(|builder| {
37///     builder.add_read::<B>().add_read::<C>();
38/// }),)
39///     .build_state(&mut world)
40///     .build_system(resource_system);
41///
42/// world.init_resource::<A>();
43/// world.init_resource::<C>();
44///
45/// fn resource_system(res: FilteredResources) {
46///     // The resource exists, but we have no access, so we can't read it.
47///     assert!(res.get::<A>().is_err());
48///     // The resource doesn't exist, so we can't read it.
49///     assert!(res.get::<B>().is_err());
50///     // The resource exists and we have access, so we can read it.
51///     let c = res.get::<C>().unwrap();
52///     // The type parameter can be left out if it can be determined from use.
53///     let c: Ref<C> = res.get().unwrap();
54/// }
55/// #
56/// # world.run_system_once(system);
57/// ```
58///
59/// This can be used alongside ordinary [`Res`](crate::system::Res) and [`ResMut`](crate::system::ResMut) parameters if they do not conflict.
60///
61/// ```
62/// # use bevy_ecs::{prelude::*, system::*};
63/// #
64/// # #[derive(Default, Resource)]
65/// # struct A;
66/// #
67/// # #[derive(Default, Resource)]
68/// # struct B;
69/// #
70/// # let mut world = World::new();
71/// # world.init_resource::<A>();
72/// # world.init_resource::<B>();
73/// #
74/// let system = (
75///     FilteredResourcesParamBuilder::new(|builder| {
76///         builder.add_read::<A>();
77///     }),
78///     ParamBuilder,
79///     ParamBuilder,
80/// )
81///     .build_state(&mut world)
82///     .build_system(resource_system);
83///
84/// // Read access to A does not conflict with read access to A or write access to B.
85/// fn resource_system(filtered: FilteredResources, res_a: Res<A>, res_mut_b: ResMut<B>) {
86///     let res_a_2: Ref<A> = filtered.get::<A>().unwrap();
87/// }
88/// #
89/// # world.run_system_once(system);
90/// ```
91///
92/// But it will conflict if it tries to read the same resource that another parameter writes.
93///
94/// ```should_panic
95/// # use bevy_ecs::{prelude::*, system::*};
96/// #
97/// # #[derive(Default, Resource)]
98/// # struct A;
99/// #
100/// # let mut world = World::new();
101/// # world.init_resource::<A>();
102/// #
103/// let system = (
104///     FilteredResourcesParamBuilder::new(|builder| {
105///         builder.add_read::<A>();
106///     }),
107///     ParamBuilder,
108/// )
109///     .build_state(&mut world)
110///     .build_system(invalid_resource_system);
111///
112/// // Read access to A conflicts with write access to A.
113/// fn invalid_resource_system(filtered: FilteredResources, res_mut_a: ResMut<A>) { }
114/// #
115/// # world.run_system_once(system);
116/// ```
117#[derive(Clone, Copy)]
118pub struct FilteredResources<'w, 's> {
119    world: UnsafeWorldCell<'w>,
120    access: &'s Access<ComponentId>,
121    last_run: Tick,
122    this_run: Tick,
123}
124
125impl<'w, 's> FilteredResources<'w, 's> {
126    /// Creates a new [`FilteredResources`].
127    /// # Safety
128    /// It is the callers responsibility to ensure that nothing else may access the any resources in the `world` in a way that conflicts with `access`.
129    pub(crate) unsafe fn new(
130        world: UnsafeWorldCell<'w>,
131        access: &'s Access<ComponentId>,
132        last_run: Tick,
133        this_run: Tick,
134    ) -> Self {
135        Self {
136            world,
137            access,
138            last_run,
139            this_run,
140        }
141    }
142
143    /// Returns a reference to the underlying [`Access`].
144    pub fn access(&self) -> &Access<ComponentId> {
145        self.access
146    }
147
148    /// Returns `true` if the `FilteredResources` has access to the given resource.
149    /// Note that [`Self::get()`] may still return `Err` if the resource does not exist.
150    pub fn has_read<R: Resource>(&self) -> bool {
151        let component_id = self.world.components().resource_id::<R>();
152        component_id.is_some_and(|component_id| self.access.has_resource_read(component_id))
153    }
154
155    /// Gets a reference to the resource of the given type if it exists and the `FilteredResources` has access to it.
156    pub fn get<R: Resource>(&self) -> Result<Ref<'w, R>, ResourceFetchError> {
157        let component_id = self
158            .world
159            .components()
160            .resource_id::<R>()
161            .ok_or(ResourceFetchError::NotRegistered)?;
162        if !self.access.has_resource_read(component_id) {
163            return Err(ResourceFetchError::NoResourceAccess(component_id));
164        }
165
166        // SAFETY: We have read access to this resource
167        let (value, ticks, caller) = unsafe { self.world.get_resource_with_ticks(component_id) }
168            .ok_or(ResourceFetchError::DoesNotExist(component_id))?;
169
170        Ok(Ref {
171            // SAFETY: `component_id` was obtained from the type ID of `R`.
172            value: unsafe { value.deref() },
173            // SAFETY: We have read access to the resource, so no mutable reference can exist.
174            ticks: unsafe { Ticks::from_tick_cells(ticks, self.last_run, self.this_run) },
175            // SAFETY: We have read access to the resource, so no mutable reference can exist.
176            changed_by: unsafe { caller.map(|caller| caller.deref()) },
177        })
178    }
179
180    /// Gets a pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
181    pub fn get_by_id(&self, component_id: ComponentId) -> Result<Ptr<'w>, ResourceFetchError> {
182        if !self.access.has_resource_read(component_id) {
183            return Err(ResourceFetchError::NoResourceAccess(component_id));
184        }
185        // SAFETY: We have read access to this resource
186        unsafe { self.world.get_resource_by_id(component_id) }
187            .ok_or(ResourceFetchError::DoesNotExist(component_id))
188    }
189}
190
191impl<'w, 's> From<FilteredResourcesMut<'w, 's>> for FilteredResources<'w, 's> {
192    fn from(resources: FilteredResourcesMut<'w, 's>) -> Self {
193        // SAFETY:
194        // - `FilteredResourcesMut` guarantees exclusive access to all resources in the new `FilteredResources`.
195        unsafe {
196            FilteredResources::new(
197                resources.world,
198                resources.access,
199                resources.last_run,
200                resources.this_run,
201            )
202        }
203    }
204}
205
206impl<'w, 's> From<&'w FilteredResourcesMut<'_, 's>> for FilteredResources<'w, 's> {
207    fn from(resources: &'w FilteredResourcesMut<'_, 's>) -> Self {
208        // SAFETY:
209        // - `FilteredResourcesMut` guarantees exclusive access to all components in the new `FilteredResources`.
210        unsafe {
211            FilteredResources::new(
212                resources.world,
213                resources.access,
214                resources.last_run,
215                resources.this_run,
216            )
217        }
218    }
219}
220
221impl<'w> From<&'w World> for FilteredResources<'w, 'static> {
222    fn from(value: &'w World) -> Self {
223        const READ_ALL_RESOURCES: &Access<ComponentId> = {
224            const ACCESS: Access<ComponentId> = {
225                let mut access = Access::new();
226                access.read_all_resources();
227                access
228            };
229            &ACCESS
230        };
231
232        let last_run = value.last_change_tick();
233        let this_run = value.read_change_tick();
234        // SAFETY: We have a reference to the entire world, so nothing else can alias with read access to all resources.
235        unsafe {
236            Self::new(
237                value.as_unsafe_world_cell_readonly(),
238                READ_ALL_RESOURCES,
239                last_run,
240                this_run,
241            )
242        }
243    }
244}
245
246impl<'w> From<&'w mut World> for FilteredResources<'w, 'static> {
247    fn from(value: &'w mut World) -> Self {
248        Self::from(&*value)
249    }
250}
251
252/// Provides mutable access to a set of [`Resource`]s defined by the contained [`Access`].
253///
254/// Use [`FilteredResources`] if you only need read-only access to resources.
255///
256/// To be useful as a [`SystemParam`](crate::system::SystemParam),
257/// this must be configured using a [`FilteredResourcesMutParamBuilder`](crate::system::FilteredResourcesMutParamBuilder)
258/// to build the system using a [`SystemParamBuilder`](crate::prelude::SystemParamBuilder).
259///
260/// # Examples
261///
262/// ```
263/// # use bevy_ecs::{prelude::*, system::*};
264/// #
265/// # #[derive(Default, Resource)]
266/// # struct A;
267/// #
268/// # #[derive(Default, Resource)]
269/// # struct B;
270/// #
271/// # #[derive(Default, Resource)]
272/// # struct C;
273/// #
274/// # #[derive(Default, Resource)]
275/// # struct D;
276/// #
277/// # let mut world = World::new();
278/// // Use `FilteredResourcesMutParamBuilder` to declare access to resources.
279/// let system = (FilteredResourcesMutParamBuilder::new(|builder| {
280///     builder.add_write::<B>().add_read::<C>().add_write::<D>();
281/// }),)
282///     .build_state(&mut world)
283///     .build_system(resource_system);
284///
285/// world.init_resource::<A>();
286/// world.init_resource::<C>();
287/// world.init_resource::<D>();
288///
289/// fn resource_system(mut res: FilteredResourcesMut) {
290///     // The resource exists, but we have no access, so we can't read it or write it.
291///     assert!(res.get::<A>().is_err());
292///     assert!(res.get_mut::<A>().is_err());
293///     // The resource doesn't exist, so we can't read it or write it.
294///     assert!(res.get::<B>().is_err());
295///     assert!(res.get_mut::<B>().is_err());
296///     // The resource exists and we have read access, so we can read it but not write it.
297///     let c = res.get::<C>().unwrap();
298///     assert!(res.get_mut::<C>().is_err());
299///     // The resource exists and we have write access, so we can read it or write it.
300///     let d = res.get::<D>().unwrap();
301///     let d = res.get_mut::<D>().unwrap();
302///     // The type parameter can be left out if it can be determined from use.
303///     let c: Ref<C> = res.get().unwrap();
304/// }
305/// #
306/// # world.run_system_once(system);
307/// ```
308///
309/// This can be used alongside ordinary [`Res`](crate::system::ResMut) and [`ResMut`](crate::system::ResMut) parameters if they do not conflict.
310///
311/// ```
312/// # use bevy_ecs::{prelude::*, system::*};
313/// #
314/// # #[derive(Default, Resource)]
315/// # struct A;
316/// #
317/// # #[derive(Default, Resource)]
318/// # struct B;
319/// #
320/// # #[derive(Default, Resource)]
321/// # struct C;
322/// #
323/// # let mut world = World::new();
324/// # world.init_resource::<A>();
325/// # world.init_resource::<B>();
326/// # world.init_resource::<C>();
327/// #
328/// let system = (
329///     FilteredResourcesMutParamBuilder::new(|builder| {
330///         builder.add_read::<A>().add_write::<B>();
331///     }),
332///     ParamBuilder,
333///     ParamBuilder,
334/// )
335///     .build_state(&mut world)
336///     .build_system(resource_system);
337///
338/// // Read access to A does not conflict with read access to A or write access to C.
339/// // Write access to B does not conflict with access to A or C.
340/// fn resource_system(mut filtered: FilteredResourcesMut, res_a: Res<A>, res_mut_c: ResMut<C>) {
341///     let res_a_2: Ref<A> = filtered.get::<A>().unwrap();
342///     let res_mut_b: Mut<B> = filtered.get_mut::<B>().unwrap();
343/// }
344/// #
345/// # world.run_system_once(system);
346/// ```
347///
348/// But it will conflict if it tries to read the same resource that another parameter writes,
349/// or write the same resource that another parameter reads.
350///
351/// ```should_panic
352/// # use bevy_ecs::{prelude::*, system::*};
353/// #
354/// # #[derive(Default, Resource)]
355/// # struct A;
356/// #
357/// # let mut world = World::new();
358/// # world.init_resource::<A>();
359/// #
360/// let system = (
361///     FilteredResourcesMutParamBuilder::new(|builder| {
362///         builder.add_write::<A>();
363///     }),
364///     ParamBuilder,
365/// )
366///     .build_state(&mut world)
367///     .build_system(invalid_resource_system);
368///
369/// // Read access to A conflicts with write access to A.
370/// fn invalid_resource_system(filtered: FilteredResourcesMut, res_a: Res<A>) { }
371/// #
372/// # world.run_system_once(system);
373/// ```
374pub struct FilteredResourcesMut<'w, 's> {
375    world: UnsafeWorldCell<'w>,
376    access: &'s Access<ComponentId>,
377    last_run: Tick,
378    this_run: Tick,
379}
380
381impl<'w, 's> FilteredResourcesMut<'w, 's> {
382    /// Creates a new [`FilteredResources`].
383    /// # Safety
384    /// It is the callers responsibility to ensure that nothing else may access the any resources in the `world` in a way that conflicts with `access`.
385    pub(crate) unsafe fn new(
386        world: UnsafeWorldCell<'w>,
387        access: &'s Access<ComponentId>,
388        last_run: Tick,
389        this_run: Tick,
390    ) -> Self {
391        Self {
392            world,
393            access,
394            last_run,
395            this_run,
396        }
397    }
398
399    /// Gets read-only access to all of the resources this `FilteredResourcesMut` can access.
400    pub fn as_readonly(&self) -> FilteredResources<'_, 's> {
401        FilteredResources::from(self)
402    }
403
404    /// Returns a new instance with a shorter lifetime.
405    /// This is useful if you have `&mut FilteredResourcesMut`, but you need `FilteredResourcesMut`.
406    pub fn reborrow(&mut self) -> FilteredResourcesMut<'_, 's> {
407        // SAFETY: We have exclusive access to this access for the duration of `'_`, so there cannot be anything else that conflicts.
408        unsafe { Self::new(self.world, self.access, self.last_run, self.this_run) }
409    }
410
411    /// Returns a reference to the underlying [`Access`].
412    pub fn access(&self) -> &Access<ComponentId> {
413        self.access
414    }
415
416    /// Returns `true` if the `FilteredResources` has read access to the given resource.
417    /// Note that [`Self::get()`] may still return `Err` if the resource does not exist.
418    pub fn has_read<R: Resource>(&self) -> bool {
419        let component_id = self.world.components().resource_id::<R>();
420        component_id.is_some_and(|component_id| self.access.has_resource_read(component_id))
421    }
422
423    /// Returns `true` if the `FilteredResources` has write access to the given resource.
424    /// Note that [`Self::get_mut()`] may still return `Err` if the resource does not exist.
425    pub fn has_write<R: Resource>(&self) -> bool {
426        let component_id = self.world.components().resource_id::<R>();
427        component_id.is_some_and(|component_id| self.access.has_resource_write(component_id))
428    }
429
430    /// Gets a reference to the resource of the given type if it exists and the `FilteredResources` has access to it.
431    pub fn get<R: Resource>(&self) -> Result<Ref<'_, R>, ResourceFetchError> {
432        self.as_readonly().get()
433    }
434
435    /// Gets a pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
436    pub fn get_by_id(&self, component_id: ComponentId) -> Result<Ptr<'_>, ResourceFetchError> {
437        self.as_readonly().get_by_id(component_id)
438    }
439
440    /// Gets a mutable reference to the resource of the given type if it exists and the `FilteredResources` has access to it.
441    pub fn get_mut<R: Resource>(&mut self) -> Result<Mut<'_, R>, ResourceFetchError> {
442        // SAFETY: We have exclusive access to the resources in `access` for `'_`, and we shorten the returned lifetime to that.
443        unsafe { self.get_mut_unchecked() }
444    }
445
446    /// Gets a mutable pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
447    pub fn get_mut_by_id(
448        &mut self,
449        component_id: ComponentId,
450    ) -> Result<MutUntyped<'_>, ResourceFetchError> {
451        // SAFETY: We have exclusive access to the resources in `access` for `'_`, and we shorten the returned lifetime to that.
452        unsafe { self.get_mut_by_id_unchecked(component_id) }
453    }
454
455    /// Consumes self and gets mutable access to resource of the given type with the world `'w` lifetime if it exists and the `FilteredResources` has access to it.
456    pub fn into_mut<R: Resource>(mut self) -> Result<Mut<'w, R>, ResourceFetchError> {
457        // SAFETY: This consumes self, so we have exclusive access to the resources in `access` for the entirety of `'w`.
458        unsafe { self.get_mut_unchecked() }
459    }
460
461    /// Consumes self and gets mutable access to resource with the given [`ComponentId`] with the world `'w` lifetime if it exists and the `FilteredResources` has access to it.
462    pub fn into_mut_by_id(
463        mut self,
464        component_id: ComponentId,
465    ) -> Result<MutUntyped<'w>, ResourceFetchError> {
466        // SAFETY: This consumes self, so we have exclusive access to the resources in `access` for the entirety of `'w`.
467        unsafe { self.get_mut_by_id_unchecked(component_id) }
468    }
469
470    /// Gets a mutable pointer to the resource of the given type if it exists and the `FilteredResources` has access to it.
471    /// # Safety
472    /// It is the callers responsibility to ensure that there are no conflicting borrows of anything in `access` for the duration of the returned value.
473    unsafe fn get_mut_unchecked<R: Resource>(&mut self) -> Result<Mut<'w, R>, ResourceFetchError> {
474        let component_id = self
475            .world
476            .components()
477            .resource_id::<R>()
478            .ok_or(ResourceFetchError::NotRegistered)?;
479        // SAFETY: THe caller ensures that there are no conflicting borrows.
480        unsafe { self.get_mut_by_id_unchecked(component_id) }
481            // SAFETY: The underlying type of the resource is `R`.
482            .map(|ptr| unsafe { ptr.with_type::<R>() })
483    }
484
485    /// Gets a mutable pointer to the resource with the given [`ComponentId`] if it exists and the `FilteredResources` has access to it.
486    /// # Safety
487    /// It is the callers responsibility to ensure that there are no conflicting borrows of anything in `access` for the duration of the returned value.
488    unsafe fn get_mut_by_id_unchecked(
489        &mut self,
490        component_id: ComponentId,
491    ) -> Result<MutUntyped<'w>, ResourceFetchError> {
492        if !self.access.has_resource_write(component_id) {
493            return Err(ResourceFetchError::NoResourceAccess(component_id));
494        }
495
496        // SAFETY: We have read access to this resource
497        let (value, ticks, caller) = unsafe { self.world.get_resource_with_ticks(component_id) }
498            .ok_or(ResourceFetchError::DoesNotExist(component_id))?;
499
500        Ok(MutUntyped {
501            // SAFETY: We have exclusive access to the underlying storage.
502            value: unsafe { value.assert_unique() },
503            // SAFETY: We have exclusive access to the underlying storage.
504            ticks: unsafe { TicksMut::from_tick_cells(ticks, self.last_run, self.this_run) },
505            // SAFETY: We have exclusive access to the underlying storage.
506            changed_by: unsafe { caller.map(|caller| caller.deref_mut()) },
507        })
508    }
509}
510
511impl<'w> From<&'w mut World> for FilteredResourcesMut<'w, 'static> {
512    fn from(value: &'w mut World) -> Self {
513        const WRITE_ALL_RESOURCES: &Access<ComponentId> = {
514            const ACCESS: Access<ComponentId> = {
515                let mut access = Access::new();
516                access.write_all_resources();
517                access
518            };
519            &ACCESS
520        };
521
522        let last_run = value.last_change_tick();
523        let this_run = value.change_tick();
524        // SAFETY: We have a mutable reference to the entire world, so nothing else can alias with mutable access to all resources.
525        unsafe {
526            Self::new(
527                value.as_unsafe_world_cell_readonly(),
528                WRITE_ALL_RESOURCES,
529                last_run,
530                this_run,
531            )
532        }
533    }
534}
535
536/// Builder struct to define the access for a [`FilteredResources`].
537///
538/// This is passed to a callback in [`FilteredResourcesParamBuilder`](crate::system::FilteredResourcesParamBuilder).
539pub struct FilteredResourcesBuilder<'w> {
540    world: &'w mut World,
541    access: Access<ComponentId>,
542}
543
544impl<'w> FilteredResourcesBuilder<'w> {
545    /// Creates a new builder with no access.
546    pub fn new(world: &'w mut World) -> Self {
547        Self {
548            world,
549            access: Access::new(),
550        }
551    }
552
553    /// Returns a reference to the underlying [`Access`].
554    pub fn access(&self) -> &Access<ComponentId> {
555        &self.access
556    }
557
558    /// Add accesses required to read all resources.
559    pub fn add_read_all(&mut self) -> &mut Self {
560        self.access.read_all_resources();
561        self
562    }
563
564    /// Add accesses required to read the resource of the given type.
565    pub fn add_read<R: Resource>(&mut self) -> &mut Self {
566        let component_id = self.world.components_registrator().register_resource::<R>();
567        self.add_read_by_id(component_id)
568    }
569
570    /// Add accesses required to read the resource with the given [`ComponentId`].
571    pub fn add_read_by_id(&mut self, component_id: ComponentId) -> &mut Self {
572        self.access.add_resource_read(component_id);
573        self
574    }
575
576    /// Create an [`Access`] that represents the accesses of the builder.
577    pub fn build(self) -> Access<ComponentId> {
578        self.access
579    }
580}
581
582/// Builder struct to define the access for a [`FilteredResourcesMut`].
583///
584/// This is passed to a callback in [`FilteredResourcesMutParamBuilder`](crate::system::FilteredResourcesMutParamBuilder).
585pub struct FilteredResourcesMutBuilder<'w> {
586    world: &'w mut World,
587    access: Access<ComponentId>,
588}
589
590impl<'w> FilteredResourcesMutBuilder<'w> {
591    /// Creates a new builder with no access.
592    pub fn new(world: &'w mut World) -> Self {
593        Self {
594            world,
595            access: Access::new(),
596        }
597    }
598
599    /// Returns a reference to the underlying [`Access`].
600    pub fn access(&self) -> &Access<ComponentId> {
601        &self.access
602    }
603
604    /// Add accesses required to read all resources.
605    pub fn add_read_all(&mut self) -> &mut Self {
606        self.access.read_all_resources();
607        self
608    }
609
610    /// Add accesses required to read the resource of the given type.
611    pub fn add_read<R: Resource>(&mut self) -> &mut Self {
612        let component_id = self.world.components_registrator().register_resource::<R>();
613        self.add_read_by_id(component_id)
614    }
615
616    /// Add accesses required to read the resource with the given [`ComponentId`].
617    pub fn add_read_by_id(&mut self, component_id: ComponentId) -> &mut Self {
618        self.access.add_resource_read(component_id);
619        self
620    }
621
622    /// Add accesses required to get mutable access to all resources.
623    pub fn add_write_all(&mut self) -> &mut Self {
624        self.access.write_all_resources();
625        self
626    }
627
628    /// Add accesses required to get mutable access to the resource of the given type.
629    pub fn add_write<R: Resource>(&mut self) -> &mut Self {
630        let component_id = self.world.components_registrator().register_resource::<R>();
631        self.add_write_by_id(component_id)
632    }
633
634    /// Add accesses required to get mutable access to the resource with the given [`ComponentId`].
635    pub fn add_write_by_id(&mut self, component_id: ComponentId) -> &mut Self {
636        self.access.add_resource_write(component_id);
637        self
638    }
639
640    /// Create an [`Access`] that represents the accesses of the builder.
641    pub fn build(self) -> Access<ComponentId> {
642        self.access
643    }
644}