despero_hecs_schedule/
access.rs

1use std::any::{type_name, TypeId};
2
3use hecs::{Fetch, Query};
4
5use crate::borrow::ComponentBorrow;
6
7#[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq)]
8/// Describes how a type is accessed.
9pub struct Access {
10    pub(crate) name: &'static str,
11    pub(crate) id: TypeId,
12    pub(crate) exclusive: bool,
13}
14
15impl std::fmt::Debug for Access {
16    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
17        if self.exclusive {
18            write!(f, "mut {}", self.name)
19        } else {
20            write!(f, "{}", self.name)
21        }
22    }
23}
24
25impl Access {
26    /// Create a new access
27    pub fn new(name: &'static str, id: TypeId, exclusive: bool) -> Self {
28        Self {
29            name,
30            id,
31            exclusive,
32        }
33    }
34
35    /// Creates a new access from a known  type
36    pub fn of<T: IntoAccess>() -> Self {
37        T::access()
38    }
39
40    /// Get a reference to the access's exclusive.
41    #[inline]
42    pub fn exclusive(&self) -> bool {
43        self.exclusive
44    }
45
46    /// Get the id
47    #[inline]
48    pub fn id(&self) -> std::any::TypeId {
49        self.id
50    }
51
52    /// Get typename
53    #[inline]
54    pub fn name(&self) -> &'static str {
55        self.name
56    }
57}
58
59/// Convert a type into the correspodning access.
60pub trait IntoAccess {
61    /// Performs the conversion.
62    fn access() -> Access;
63    /// Check if the borrow is compatible with another borrow.
64    /// A &T is compatible with &T, but not &mut T.
65    /// A &mut T is compatible with &T and &mut T.
66    fn compatible<U: IntoAccess>() -> bool {
67        let l = Self::access();
68        let r = U::access();
69
70        l.id == r.id && (!r.exclusive || r.exclusive == l.exclusive)
71    }
72}
73
74impl<T: 'static> IntoAccess for &T {
75    fn access() -> Access {
76        Access {
77            id: TypeId::of::<T>(),
78            exclusive: false,
79            name: type_name::<T>(),
80        }
81    }
82}
83
84impl<T: 'static> IntoAccess for &mut T {
85    fn access() -> Access {
86        Access {
87            id: TypeId::of::<T>(),
88            exclusive: true,
89            name: type_name::<T>(),
90        }
91    }
92}
93
94/// Marker type for a subworld which has access to the whole world
95pub struct AllAccess;
96
97/// Declare subset relations between tuples
98pub trait Subset {
99    /// Returns true if U is a subset of Self
100    fn is_subset<U: ComponentBorrow>() -> bool;
101}
102
103impl<'a, Q: Query> Subset for Q {
104    fn is_subset<U: ComponentBorrow>() -> bool {
105        let mut all = true;
106        Q::Fetch::for_each_borrow(|id, exclusive| {
107            if !U::has_dynamic(id, exclusive) {
108                all = false
109            }
110        });
111
112        all
113    }
114}