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}