async_ecs/access/accessor.rs
1use std::marker::PhantomData;
2use std::ops::Deref;
3
4use crate::{
5 resource::ResourceId,
6 system::{DynamicSystemData, SystemData},
7};
8
9/// A trait for accessing read/write multiple resources from a system. This can
10/// be used to create dynamic systems that don't specify what they fetch at
11/// compile-time.
12///
13/// For compile-time system data this will all be done for you using
14/// `StaticAccessor`.
15pub trait Accessor: Sized {
16 /// A list of [`ResourceId`]s the bundle needs read access to in order to
17 /// build the target resource bundle.
18 ///
19 /// # Contract
20 ///
21 /// Exactly return the dependencies you're going to `fetch`! Doing otherwise
22 /// *will* cause a panic.
23 ///
24 /// This method is only executed once, thus the returned value may never change
25 /// (otherwise it has no effect).
26 ///
27 /// [`ResourceId`]: struct.ResourceId.html
28 fn reads(&self) -> Vec<ResourceId> {
29 Vec::new()
30 }
31
32 /// A list of [`ResourceId`]s the bundle needs write access to in order to
33 /// build the target resource bundle.
34 ///
35 /// # Contract
36 ///
37 /// Exactly return the dependencies you're going to `fetch`! Doing otherwise
38 /// *will* cause a panic.
39 ///
40 /// This method is only executed once, thus the returned value may never change
41 /// (otherwise it has no effect).
42 ///
43 /// [`ResourceId`]: struct.ResourceId.html
44 fn writes(&self) -> Vec<ResourceId> {
45 Vec::new()
46 }
47
48 /// Tries to create a new instance of this type. This one returns `Some` in
49 /// case there is a default, otherwise the system needs to override
50 /// `System::accessor`.
51 fn try_new() -> Option<Self> {
52 None
53 }
54}
55
56pub type AccessorType<'a, T> = <T as DynamicSystemData<'a>>::Accessor;
57
58/// The static accessor that is used for `SystemData`.
59#[derive(Default)]
60pub struct StaticAccessor<T> {
61 marker: PhantomData<fn() -> T>,
62}
63
64impl<'a, T> Accessor for StaticAccessor<T>
65where
66 T: SystemData<'a>,
67{
68 fn try_new() -> Option<Self> {
69 Some(StaticAccessor {
70 marker: PhantomData,
71 })
72 }
73
74 fn reads(&self) -> Vec<ResourceId> {
75 T::reads()
76 }
77
78 fn writes(&self) -> Vec<ResourceId> {
79 T::writes()
80 }
81}
82
83pub enum AccessorCow<'a, 'b, T>
84where
85 T: DynamicSystemData<'a> + ?Sized,
86 T::Accessor: 'b,
87 'a: 'b,
88{
89 Borrow(&'b T::Accessor),
90 Owned(T::Accessor),
91}
92
93impl<'a, 'b, T> Deref for AccessorCow<'a, 'b, T>
94where
95 AccessorType<'a, T>: 'b,
96 T: DynamicSystemData<'a> + ?Sized + 'b,
97 'a: 'b,
98{
99 type Target = T::Accessor;
100
101 fn deref(&self) -> &T::Accessor {
102 match *self {
103 AccessorCow::Borrow(r) => &*r,
104 AccessorCow::Owned(ref o) => o,
105 }
106 }
107}