1 module ut.traits;
2 
3 
4 import ut;
5 import mirror.meta;
6 import mirror.traits;
7 import std.meta: AliasSeq;
8 
9 
10 @("isEnum")
11 @safe pure unittest {
12     static import modules.types;
13     import std.meta: Filter, AliasSeq;
14 
15     alias mod = Module!"modules.types";
16     alias aggregates = mod.Aggregates;
17     alias enums = Filter!(isEnum, aggregates);
18     static assert(is(enums == AliasSeq!(modules.types.Enum)), enums.stringof);
19 }
20 
21 
22 @("isStruct")
23 @safe pure unittest {
24     static import modules.types;
25     import std.meta: Filter, AliasSeq;
26 
27     alias mod = Module!"modules.types";
28     alias aggregates = mod.Aggregates;
29     alias structs = Filter!(isStruct, aggregates);
30     static assert(is(structs == AliasSeq!(modules.types.String)), structs.stringof);
31 }
32 
33 
34 @("isInterface")
35 @safe pure unittest {
36     static import modules.types;
37     import std.meta: Filter, AliasSeq;
38 
39     alias mod = Module!"modules.types";
40     alias aggregates = mod.Aggregates;
41     alias interfaces = Filter!(isInterface, aggregates);
42     static assert(is(interfaces == AliasSeq!(modules.types.Interface)), interfaces.stringof);
43 }
44 
45 
46 @("isClass")
47 @safe pure unittest {
48     static import modules.types;
49     import std.meta: Filter, AliasSeq;
50 
51     alias mod = Module!"modules.types";
52     alias aggregates = mod.Aggregates;
53     alias classes = Filter!(isClass, aggregates);
54     alias expected = AliasSeq!(
55         modules.types.Class,
56         modules.types.AbstractClass,
57         modules.types.MiddleClass,
58         modules.types.LeafClass,
59     );
60     static assert(is(classes == expected), classes.stringof);
61 }
62 
63 
64 @("isOOP")
65 @safe pure unittest {
66     static import modules.types;
67     import std.meta: Filter, AliasSeq;
68 
69     alias mod = Module!"modules.types";
70     alias aggregates = mod.Aggregates;
71     alias classes = Filter!(isOOP, aggregates);
72     alias expected = AliasSeq!(
73         modules.types.Class,
74         modules.types.Interface,
75         modules.types.AbstractClass,
76         modules.types.MiddleClass,
77         modules.types.LeafClass,
78     );
79     static assert(is(classes == expected), classes.stringof);
80 }
81 
82 
83 @("FundamentalType.scalar")
84 @safe pure unittest {
85     static assert(is(FundamentalType!int == int));
86     static assert(is(FundamentalType!double == double));
87     static struct Foo { }
88     static assert(is(FundamentalType!Foo == Foo));
89 }
90 
91 
92 @("FundamentalType.array")
93 @safe pure unittest {
94     static assert(is(FundamentalType!(int[]) == int));
95     static assert(is(FundamentalType!(int[][]) == int));
96     static assert(is(FundamentalType!(int[][][]) == int));
97 
98     static assert(is(FundamentalType!(double[]) == double));
99     static assert(is(FundamentalType!(double[][]) == double));
100 
101     static assert(is(FundamentalType!string == immutable char));
102     static assert(is(FundamentalType!(string[]) == immutable char));
103 
104     static struct Foo { }
105     static assert(is(FundamentalType!(Foo[]) == Foo));
106     static assert(is(FundamentalType!(Foo[][]) == Foo));
107 }
108 
109 
110 @("FundamentalType.pointer")
111 @safe pure unittest {
112     static assert(is(FundamentalType!(int*) == int));
113     static assert(is(FundamentalType!(int**) == int));
114     static assert(is(FundamentalType!(int***) == int));
115 
116     static assert(is(FundamentalType!(double*) == double));
117     static assert(is(FundamentalType!(double**) == double));
118 
119     static assert(is(FundamentalType!(string*) == immutable char));
120     static assert(is(FundamentalType!(string**) == immutable char));
121 
122     static struct Foo { }
123     static assert(is(FundamentalType!(Foo*) == Foo));
124     static assert(is(FundamentalType!(Foo**) == Foo));
125 }
126 
127 
128 @("RecursiveFieldTypes.scalar")
129 @safe pure unittest {
130     static assert(is(RecursiveFieldTypes!int == int));
131     static assert(is(RecursiveFieldTypes!double == double));
132 }
133 
134 
135 @("RecursiveFieldTypes.udt.flat")
136 @safe pure unittest {
137 
138     static struct Foo {
139         int i;
140         double d;
141     }
142 
143     shouldEqual!(RecursiveFieldTypes!Foo, AliasSeq!(int, double));
144 }
145 
146 
147 @("RecursiveFieldTypes.udt.nested")
148 @safe pure unittest {
149 
150     static struct Inner0 {
151         int i;
152         double d;
153     }
154 
155     static struct Inner1 {
156         double d;
157         string s;
158     }
159 
160     static struct Mid {
161         Inner0 inner0;
162         Inner1 inner1;
163     }
164 
165     static struct Outer {
166         Mid mid;
167         byte b;
168         float func(float, float);
169 
170         @property static Outer max() @safe pure nothrow @nogc {
171             return Outer();
172         }
173     }
174 
175     shouldEqual!(RecursiveFieldTypes!Outer,
176                  AliasSeq!(Mid, Inner0, int, double, Inner1, string, byte));
177 }
178 
179 
180 @("RecursiveFieldTypes.udt.Date")
181 @safe pure unittest {
182 
183     import std.datetime: Date, Month;
184 
185     static struct Struct {
186         int i;
187         Date date;
188     }
189 
190     shouldEqual!(RecursiveFieldTypes!Struct,
191                  AliasSeq!(int, Date, short, Month, ubyte));
192 }
193 
194 
195 @("RecursiveFieldTypes.udt.DateTime")
196 @safe pure unittest {
197 
198     import std.datetime: Date, DateTime, Month, TimeOfDay;
199 
200     static struct Struct {
201         int i;
202         DateTime date;
203     }
204 
205     shouldEqual!(RecursiveFieldTypes!Struct,
206                  AliasSeq!(int, DateTime, Date, short, Month, ubyte, TimeOfDay));
207 }
208 
209 
210 @("RecursiveFieldTypes.udt.composite.struct")
211 @safe pure unittest {
212 
213     static struct Struct {
214         Struct* child;
215     }
216 
217     shouldEqual!(RecursiveFieldTypes!Struct, Struct*);
218 }
219 
220 
221 @("RecursiveFieldTypes.udt.composite.class.simple")
222 @safe pure unittest {
223 
224     static class Class {
225         Class child;
226     }
227 
228     shouldEqual!(RecursiveFieldTypes!Class, Class);
229 }
230 
231 
232 @("RecursiveFieldTypes.udt.composite.class.multiple")
233 @safe pure unittest {
234 
235     shouldEqual!(RecursiveFieldTypes!RecursiveClass0,
236                  AliasSeq!(RecursiveClass1, RecursiveClass2));
237 }
238 
239 
240 private class RecursiveClass0 {
241     RecursiveClass1 child;
242 }
243 
244 private class RecursiveClass1 {
245     RecursiveClass2 child;
246 }
247 
248 private class RecursiveClass2 {
249     RecursiveClass0 child;
250 }
251 
252 
253 @("RecursiveFieldTypes.udt.composite.array")
254 @safe pure unittest {
255 
256     static struct Point(T) {
257         T x, y;
258     }
259 
260     struct Inner1(T) {
261         Point!T point;
262         T value;
263     }
264 
265     struct EvenInner(T) {
266         T value;
267     }
268 
269     struct Inner2(T) {
270         EvenInner!T evenInner;
271     }
272 
273     static struct Outer(T) {
274         Inner1!T[] inner1s;
275         Inner2!T inner2;
276     }
277 
278     // pragma(msg, RecursiveFieldTypes!(Outer!double));
279     shouldEqual!(RecursiveFieldTypes!(Outer!double),
280                  AliasSeq!(Inner1!double[], Point!double, double, Inner2!double, EvenInner!double));
281 }
282 
283 
284 @("RecursiveFieldTypes.SocketOSException")
285 @safe @nogc pure unittest {
286     import std.socket: SocketOSException;
287     alias types = RecursiveFieldTypes!SocketOSException;
288     //pragma(msg, types);
289     shouldEqual!(types, AliasSeq!int);
290 }
291 
292 
293 @("isProperty.struct")
294 @safe @nogc pure unittest {
295 
296     static struct Struct {
297         int _i;
298         @property int i();
299         @property void i(int i);
300         int foo(double d);
301     }
302 
303     static assert(isProperty!(__traits(getOverloads, Struct, "i")[1]));
304     static assert(isProperty!(__traits(getOverloads, Struct, "i")[1]));
305     static assert(!isProperty!(Struct.foo));
306 }
307 
308 
309 @("isProperty.class")
310 @safe @nogc pure unittest {
311 
312     static class Class {
313         int _i;
314         @property int i() { return _i; }
315         @property void i(int i) { _i = i; }
316         int foo(double d) { return i * 2; }
317     }
318 
319     static assert(isProperty!(__traits(getOverloads, Class, "i")[1]));
320     static assert(isProperty!(__traits(getOverloads, Class, "i")[1]));
321     static assert(!isProperty!(Class.foo));
322 }
323 
324 
325 @("MemberFunctions.struct")
326 @safe @nogc pure unittest {
327 
328     static struct Struct {
329         private int _i;
330         @property int i();
331         @property void i(int i);
332         int foo(double d);
333         string bar(int i);
334     }
335 
336     //pragma(msg, "MemberFunctions.struct: ", MemberFunctions!Struct.stringof);
337 
338     shouldEqual!(
339         MemberFunctions!Struct,
340         AliasSeq!(
341             __traits(getOverloads, Struct, "i")[0],
342             __traits(getOverloads, Struct, "i")[1],
343             Struct.foo,
344             Struct.bar,
345         )
346     );
347 }
348 
349 
350 @("MemberFunctions.class")
351 @safe @nogc pure unittest {
352 
353     static class Class {
354         private int _i;
355         @property int i() { return _i; }
356         @property void i(int i) { _i = i; }
357         int foo(double d) { return cast(int) (d * 2); }
358         string bar(int i) { return "foobar"; }
359     }
360 
361     //pragma(msg, "MemberFunctions.class: ", MemberFunctions!Class.stringof);
362 
363     shouldEqual!(
364         MemberFunctions!Class,
365         AliasSeq!(
366             __traits(getOverloads, Class, "i")[0],
367             __traits(getOverloads, Class, "i")[1],
368             Class.foo,
369             Class.bar,
370         )
371     );
372 }
373 
374 
375 @("PublicMembers.std.socket")
376 @safe @nogc pure unittest {
377     import std.socket;
378     alias members = PublicMembers!(std.socket);
379 }