ecstatic/
traits.rs

1// Copyright 2018 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::*;
16
17/// Trait that allows us to convert flat tuple types to nested tuple types (e.g.,
18/// `(A, B, C)` → `(A, (B, (C, ())))`).
19///
20/// Also provides an associated function to convert a nested tuple **by value** to the equivalent
21/// flat tuple.
22///
23/// This trait is provided for tuples up to length 32.
24pub trait Nest: private::Sealed {
25    /// Equivalent nested tuple type.
26    type Nested;
27    /// Convert a nested tuple to its flat representation.
28    fn flatten(v: Self::Nested) -> Self;
29    /// Convert `self` to its nested representation.
30    fn nest(self) -> Self::Nested;
31}
32
33/// Inverse of `Nest`.
34pub trait Flatten: private::Sealed {
35    /// Equivalent flat tuple type.
36    type Flattened;
37    /// Convert `self` to its flat representation.
38    fn flatten(self) -> Self::Flattened;
39    /// Convert a flat tuple to its nested representation.
40    fn nest(v: Self::Flattened) -> Self;
41}
42
43// helper macros for `impl_nested!`.
44macro_rules! unnest {
45    (($layer:expr); ($($v:expr),*); ($u:ident, $($us:ident,)*)) => {
46        unnest!(($layer . 1); ($($v,)* $layer . 0); ($($us,)*))
47    };
48    (($layer:expr); ($($v:expr),*); ()) => { ($($v,)*) };
49}
50
51impl Nest for () {
52    type Nested = ();
53    #[inline]
54    fn flatten(_v: ()) -> () {
55        ()
56    }
57    #[inline]
58    fn nest(self) -> () {
59        ()
60    }
61}
62
63macro_rules! nest {
64    ($v:ident,) => { () };
65    ($v:ident, $n:tt, $($ns:tt,)*) => {
66        ($v.$n, nest!($v, $($ns,)*))
67    }
68}
69
70// Implement `Nest` for tuples up to length 32.
71macro_rules! impl_nested {
72    (@impl_internal {($t:ident, $n:tt), $(($ts:ident, $ns:tt),)*}) => {
73        impl<$t, $($ts),*> Nest for ($t, $($ts,)*) where ($($ts,)*): Nest {
74            type Nested = impl_nested!(@nest_type $t, $($ts,)*);
75            #[inline]
76            fn flatten(v: Self::Nested) -> Self {
77                unnest!((v); (); ($t, $($ts,)*))
78            }
79            #[inline]
80            fn nest(self) -> Self::Nested {
81                nest!(self, $n, $($ns,)*)
82            }
83        }
84
85        impl<$t, $($ts),*> Flatten for impl_nested!(@nest_type $t, $($ts,)*) {
86            type Flattened = ($t, $($ts,)*);
87            #[inline]
88            fn flatten(self) -> Self::Flattened {
89                unnest!((self); (); ($t, $($ts,)*))
90            }
91            #[inline]
92            fn nest(v: Self::Flattened) -> Self {
93                nest!(v, $n, $($ns,)*)
94            }
95        }
96    };
97
98    (@nest_type) => {
99        ()
100    };
101
102    (@nest_type $t:ident, $($ts:ident,)*) => {
103        ($t, impl_nested!(@nest_type $($ts,)*))
104    };
105
106    // Base case
107    (@internal {$(($t:ident,$n:tt),)+}; {}; {}) => {
108        impl_nested!(@impl_internal {$(($t, $n),)*});
109    };
110
111    // Produce the actual impl for the tuple represented by $t1, then move $t2 into the tuple and
112    // recursively call impl_nested
113    (@internal {$(($t1:ident,$n1:tt),)+};
114               {$t2:ident, $($t3:ident,)*};
115               {$n2:tt, $($n3:tt,)*}) => {
116        impl_nested!(@impl_internal {$(($t1, $n1),)*});
117        impl_nested!(@internal {$(($t1, $n1),)* ($t2, $n2),};
118                               {$($t3,)*};
119                               {$($n3,)*});
120    };
121
122    // Entry point
123    (($t:ident, $($ts:ident,)+); ($n:tt, $($ns:tt,)+)) => {
124        impl_nested!(@internal {($t, $n),}; {$($ts,)*}; {$($ns,)*});
125    };
126}
127
128impl_nested!(
129    (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA, BB, CC, DD,
130    EE, FF,);
131    (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,)
132);
133
134/// Internal version of `ComponentProvider` that is implemented for nested tuples.
135pub trait ComponentProviderRec<'a, T> {
136    /// Get the components.
137    fn fetch(&'a self) -> T;
138}
139
140/// Component provider for flat tuples.
141pub trait ComponentProvider<'a, T: Nest> {
142    /// Get the components.
143    fn fetch(&'a self) -> T;
144}
145
146impl<'a, T, W> ComponentProvider<'a, T> for W
147where
148    T: Nest,
149    W: WorldInterface<'a> + ComponentProviderRec<'a, T::Nested>,
150{
151    #[inline]
152    fn fetch(&'a self) -> T {
153        <T as Nest>::flatten(<Self as ComponentProviderRec<'a, T::Nested>>::fetch(self))
154    }
155}
156
157impl<'a, H, T, WD> ComponentProviderRec<'a, (ReadComponent<'a, H>, T)> for WD
158where
159    H: 'a + StorageSpec<'a>,
160    H::Storage: ComponentStorage<'a>,
161    WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetComponent<'a, H>,
162{
163    #[inline]
164    fn fetch(&'a self) -> (ReadComponent<'a, H>, T) {
165        (
166            ReadComponent {
167                storage: <Self as GetComponent<'a, H>>::get(self),
168            },
169            <Self as ComponentProviderRec<T>>::fetch(self),
170        )
171    }
172}
173
174impl<'a, H, T, WD> ComponentProviderRec<'a, (ReadResource<'a, H>, T)> for WD
175where
176    H: 'a,
177    WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetResource<H>,
178{
179    #[inline]
180    fn fetch(&'a self) -> (ReadResource<'a, H>, T) {
181        (
182            ReadResource {
183                resource: <Self as GetResource<H>>::get(self),
184            },
185            <Self as ComponentProviderRec<T>>::fetch(self),
186        )
187    }
188}
189
190impl<'a, H, T, WD> ComponentProviderRec<'a, (WriteResource<'a, H>, T)> for WD
191where
192    H: 'a,
193    WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetResource<H>,
194{
195    #[inline]
196    fn fetch(&'a self) -> (WriteResource<'a, H>, T) {
197        (
198            WriteResource {
199                resource: <Self as GetResource<H>>::get_mut(self),
200            },
201            <Self as ComponentProviderRec<T>>::fetch(self),
202        )
203    }
204}
205
206impl<'a, H, T, WD> ComponentProviderRec<'a, (WriteComponent<'a, H>, T)> for WD
207where
208    H: 'a + StorageSpec<'a>,
209    H::Storage: ComponentStorage<'a>,
210    WD: WorldInterface<'a> + ComponentProviderRec<'a, T> + GetComponent<'a, H>,
211{
212    #[inline]
213    fn fetch(&'a self) -> (WriteComponent<'a, H>, T) {
214        (
215            WriteComponent {
216                storage: <Self as GetComponent<'a, H>>::get_mut(self),
217            },
218            <Self as ComponentProviderRec<T>>::fetch(self),
219        )
220    }
221}
222
223impl<'a, WD> ComponentProviderRec<'a, ()> for WD {
224    #[inline]
225    fn fetch(&'a self) -> () {
226        ()
227    }
228}
229
230impl<'a, WD, T> ComponentProviderRec<'a, ReadComponent<'a, T>> for WD
231where
232    T: 'a + StorageSpec<'a>,
233    WD: WorldInterface<'a> + GetComponent<'a, T>,
234{
235    fn fetch(&'a self) -> ReadComponent<T> {
236        ReadComponent {
237            storage: <Self as GetComponent<'a, T>>::get(self),
238        }
239    }
240}
241
242impl<'a, WD, T> ComponentProviderRec<'a, WriteComponent<'a, T>> for WD
243where
244    T: 'a + StorageSpec<'a>,
245    WD: WorldInterface<'a> + GetComponent<'a, T>,
246{
247    fn fetch(&'a self) -> WriteComponent<T> {
248        WriteComponent {
249            storage: <Self as GetComponent<'a, T>>::get_mut(self),
250        }
251    }
252}
253
254/// Trait that systems must implement.
255pub trait System<'a> {
256    /// The components and resources this system needs to run.
257    type Dependencies: Nest; // +IntoTypeList;
258    /// Run the system.
259    fn run(&'a mut self, dependencies: Self::Dependencies);
260}
261/// Output of `PureFunctionalSystem` for one component.
262pub enum SystemOutput<T> {
263    /// Ignore the component (neither update nor delete it).
264    Ignore,
265    /// Delete the component if it exists.
266    Delete,
267    /// Update the component with a new value.
268    Update(T),
269}
270
271impl<T> Default for SystemOutput<T> {
272    fn default() -> Self {
273        SystemOutput::Ignore
274    }
275}
276
277/// For systems that don't cause side effects or need to reason about entities or components
278/// globally, it is highly recommended that you implement `PureFunctionalSystem`, which the
279/// library will be able to automatically parallelize.
280pub trait PureFunctionalSystem {
281    /// Input types
282    type Inputs;
283    /// Output types.
284    type Outputs: SystemOutputTuple;
285    /// Process one input.
286    fn process(&self, data: &Self::Inputs) -> <Self::Outputs as SystemOutputTuple>::OutputTuple;
287}
288
289/// Interface to the `World` struct generated via the `define_world!` macro.
290pub trait WorldInterface<'a>
291where
292    Self: Sized,
293{
294    /// The type returned by `new_entity()`.
295    type EntityBuilder: 'a;
296    /// A type representing the union of every component type supported by the `World`.
297    type ComponentSet;
298    /// A `TypeList` containing all available types.
299    type AvailableTypes;
300    /// Create a new entity.
301    fn new_entity(&'a mut self) -> Self::EntityBuilder;
302    /// Consume an `EntityBuilder` and store its components. Under normal circumstances, this
303    /// should only be called by `EntityBuilder::build()`.
304    fn build_entity(&mut self, c: Self::ComponentSet) -> Entity;
305    /// Delete an entity.
306    fn delete_entity(&mut self, e: Entity);
307    /// Run a system.
308    fn run_system<'b, S, T /*, U, V*/>(&'a mut self, system: &'b mut S)
309    where
310        S: System<'b, Dependencies = T>,
311        T: Nest,
312        //U: typelist::TypeList,
313        //Self::AvailableTypes: typelist::ConsumeMultiple<U, V>,
314        Self: ComponentProviderRec<'a, T::Nested>,
315    {
316        system.run(<Self as ComponentProvider<'a, T>>::fetch(self));
317    }
318}
319
320/// Trait implemented by `EntityBuilder` types.
321pub trait BuildWith<T> {
322    /// Set the component of type `T`.
323    fn with(self, data: T) -> Self;
324}
325
326/// Get the `Resources` struct from a world generically.
327pub trait ResourceProvider {
328    /// The `Resources` struct type.
329    type Resources;
330    /// Get the resources struct.
331    fn get_resources(&mut self) -> &Self::Resources;
332}
333
334/// Indicates that the implementor stores components of type `T`.
335pub trait GetComponent<'a, T: StorageSpec<'a>> {
336    /// Get the storage.
337    fn get(&self) -> std::cell::Ref<T::Storage>;
338    /// Get the storage mutably.
339    fn get_mut(&self) -> std::cell::RefMut<T::Storage>;
340}
341
342/// Indicates that the implementor stores a resource of type `T`.
343pub trait GetResource<T> {
344    /// Get the resource.
345    fn get(&self) -> std::cell::Ref<T>;
346    /// Get the resource mutably.
347    fn get_mut(&self) -> std::cell::RefMut<T>;
348    /// Set the resource.
349    fn set(&self, t: T);
350}
351
352mod private {
353    pub trait Sealed {}
354    impl Sealed for () {}
355}
356
357/// Trait for converting tuples into tuples of `SystemOutput`s.
358pub trait SystemOutputTuple: private::Sealed {
359    /// The output of the conversion.
360    type OutputTuple;
361}
362
363// Recursive macro to implement SystemOutputTuple for tuples up to length 32
364macro_rules! impl_output_tuple {
365    (@impl_internal $($t:ident,)+) => {
366        impl<$($t),*> SystemOutputTuple for ($($t,)*) {
367            #[allow(unused_parens)]
368            type OutputTuple = ($(SystemOutput<$t>),*);
369        }
370        impl<$($t),*> private::Sealed for ($($t,)*) {}
371    };
372
373    // Base case
374    (($($t:ident,)+);) => {
375        impl_output_tuple!(@impl_internal $($t,)*);
376    };
377
378    // Produce the actual impl for the tuple represented by $t1, then move $t2 into the tuple and
379    // recursively call impl_can_provide
380    (($($t1:ident,)+); $t2:ident $(,)* $($t3:ident),*) => {
381        impl_output_tuple!(@impl_internal $($t1,)*);
382        impl_output_tuple!(($($t1),*, $t2,); $($t3),*);
383    };
384
385    // Entry point
386    ($t1:ident, $($t:ident),+) => {
387        impl_output_tuple!(($t1,); $($t),*);
388    };
389}
390
391impl_output_tuple!(
392    A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, AA, BB, CC, DD,
393    EE, FF
394);