1 /**
2 Component facilities module.
3 
4 Copyright: © 2015-2016 Claude Merle
5 Authors: Claude Merle
6 License: This file is part of EntitySysD.
7 
8 EntitySysD is free software: you can redistribute it and/or modify it
9 under the terms of the Lesser GNU General Public License as published
10 by the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12 
13 EntitySysD is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 Lesser GNU General Public License for more details.
17 
18 You should have received a copy of the Lesser GNU General Public License
19 along with EntitySysD. If not, see $(LINK http://www.gnu.org/licenses/).
20 */
21 
22 module entitysysd.component;
23 
24 // UDA for component types
25 enum component;
26 
27 /**
28  * To be a valid component, $(D C) must:
29  * - be a $(D struct) or $(D union)
30  * - have the UDA $(D component)
31  * - must contain only mutable or const fields (no $(D immutable), $(D inout) or
32  *   $(D shared) qualifiers)
33  */
34 template isComponent(C)
35 {
36     import std.meta : allSatisfy;
37     import std.traits : RepresentationTypeTuple, isMutable, hasUDA;
38 
39     enum bool isMutableOrConst(F) = isMutable!F || is(F == const);
40     static if (__traits(compiles, hasUDA!(C, component)))
41         enum bool isComponent = (is(C == struct) || is(C == union)) &&
42                                 hasUDA!(C, component) &&
43                                 allSatisfy!(isMutableOrConst,
44                                             RepresentationTypeTuple!C);
45     else
46         enum bool isComponent = false;
47 }
48 
49 template areComponents(CList...)
50 {
51     import std.meta : allSatisfy;
52     enum bool areComponents = allSatisfy!(isComponent, CList);
53 }
54 
55 
56 struct BaseComponentCounter
57 {
58     static size_t counter = 0;
59 }
60 
61 struct ComponentCounter(Derived)
62 {
63 public:
64     static size_t getId()
65     {
66         static size_t counter = -1;
67         if (counter == -1)
68         {
69             counter = mBaseComponentCounter.counter;
70             mBaseComponentCounter.counter++;
71         }
72 
73         return counter;
74     }
75 
76 private:
77     BaseComponentCounter mBaseComponentCounter;
78 }
79 
80 
81 //******************************************************************************
82 //***** UNIT-TESTS
83 //******************************************************************************
84 
85 ///
86 unittest
87 {
88     @component struct TestComponent0
89     {
90         int a, b;
91     }
92 
93     @component class TestComponent1 // component cannot be a class
94     {
95         string str;
96     }
97 
98     @component union TestComponent2
99     {
100         float f;
101         uint  u;
102     }
103 
104     static assert(!isComponent!int);
105     static assert(isComponent!TestComponent0);
106     static assert(!isComponent!TestComponent1);
107     static assert(isComponent!TestComponent2);
108 }