1 module sbylib.graphics.util.member;
2 
3 import std : isAggregateType, Filter, staticMap, AliasSeq;
4 
5 template getMembersByUDA(Aggregate, alias UDA) {
6     enum condition(alias memberInfo) = memberInfo.hasUDA!(UDA);
7     alias getMembersByUDA = Filter!(condition, getMembers!(Aggregate));
8 }
9 
10 template getMembers(Aggregate) {
11     static assert(isAggregateType!Aggregate);
12 
13     alias getMembers = staticMap!(getMembersImpl, __traits(allMembers, Aggregate));
14 
15     enum Kind {
16         Field,
17         Type,
18     }
19 
20     template getMembersImpl(string memberName) {
21         static if (memberName == "__dtor") {
22             alias getMembersImpl = AliasSeq!();
23         } else {
24             struct Result {
25                 import std : stdHasUDA = hasUDA, stdGetUDAs = getUDAs;
26 
27                 alias member = __traits(getMember, Aggregate, memberName);
28 
29                 enum name = memberName;
30 
31                 static if (is(typeof(member))) {
32                     enum kind = Kind.Field;
33                     alias type = typeof(member);
34                     enum hasType = true;
35                 } else static if (is(member)) {
36                     enum kind = Kind.Type;
37                     enum hasType = false;
38                 } else {
39                     static assert(false);
40                 }
41 
42                 static if (is(typeof(__traits(getAttributes, member)))) {
43                     alias attributes = __traits(getAttributes, member);
44                     enum hasAttributes = true;
45 
46                     enum hasUDA(alias UDA) = stdHasUDA!(member, UDA);
47                     enum getUDAs(alias UDA) = stdGetUDAs!(member, UDA);
48 
49                     template getUDA(alias UDA) {
50                         enum UDAs = getUDAs!(UDA);
51                         static assert(UDAs.length == 1);
52                         enum getUDA = UDAs[0];
53                     }
54                 } else {
55                     enum hasAttributes = false;
56                     enum hasUDA(alias UDA) = false;
57                     enum getUDAs(alias UDA) = false;
58                     enum getUDA(alias UDA) = false;
59                 }
60             }
61 
62             alias getMembersImpl = Result;
63         }
64     }
65 }