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 fields without $(D shared) qualifier)
32  */
33 template isComponent(C)
34 {
35     import std.meta : allSatisfy;
36     import std.traits : RepresentationTypeTuple, isMutable, hasUDA;
37 
38     enum bool isNotShared(F) = !is(F == shared);
39     static if (__traits(compiles, hasUDA!(C, component)))
40         enum bool isComponent = (is(C == struct) || is(C == union)) &&
41                                 hasUDA!(C, component) &&
42                                 allSatisfy!(isNotShared,
43                                             RepresentationTypeTuple!C);
44     else
45         enum bool isComponent = false;
46 }
47 
48 template areComponents(CList...)
49 {
50     import std.meta : allSatisfy;
51     enum bool areComponents = allSatisfy!(isComponent, CList);
52 }
53 
54 
55 struct BaseComponentCounter
56 {
57     static size_t counter = 0;
58 }
59 
60 struct ComponentCounter(Derived)
61 {
62 public:
63     static size_t getId()
64     {
65         static size_t counter = -1;
66         if (counter == -1)
67         {
68             counter = mBaseComponentCounter.counter;
69             mBaseComponentCounter.counter++;
70         }
71 
72         return counter;
73     }
74 
75 private:
76     BaseComponentCounter mBaseComponentCounter;
77 }
78 
79 
80 //******************************************************************************
81 //***** UNIT-TESTS
82 //******************************************************************************
83 
84 ///
85 unittest
86 {
87     @component struct TestComponent0
88     {
89         int a, b;
90     }
91 
92     @component class TestComponent1 // component cannot be a class
93     {
94         string str;
95     }
96 
97     @component union TestComponent2
98     {
99         float f;
100         uint  u;
101     }
102 
103     static assert(!isComponent!int);
104     static assert(isComponent!TestComponent0);
105     static assert(!isComponent!TestComponent1);
106     static assert(isComponent!TestComponent2);
107 }