1 module clid.core.util; 2 3 import std.traits : hasUDA, getUDAs; 4 import std.meta : Alias, anySatisfy; 5 6 import clid.attributes; 7 import clid.validate; 8 9 /** 10 * Checks if a given struct is a valid configuration struct. 11 */ 12 void validateStruct(C)() 13 { 14 static assert(is(C == struct), "Configuration object must be a struct"); 15 static foreach (member; __traits(allMembers, C)) 16 { 17 static if (!hasUDAV!(C, member, Parameter)) 18 { 19 static assert(!hasUDAV!(C, member, Description), 20 "Cannot have @Description without @Parameter in command line argument struct."); 21 static assert(!hasUDAV!(C, member, Validate), 22 "Cannot have @Validate without @Parameter in command line argument struct."); 23 } 24 } 25 } 26 27 /** 28 * Wrapper around __traits(getMember, ...) 29 */ 30 template value(C, alias m) 31 { 32 alias value = __traits(getMember, C, m); 33 } 34 35 /** 36 * Wrapper around __traits(getMember, ...) 37 */ 38 template value(alias c, alias m) 39 { 40 alias value = __traits(getMember, c, m); 41 } 42 43 /** 44 * Wrapper around hasUDA!(...) 45 */ 46 template hasUDAV(C, alias m, T) 47 { 48 alias hasUDAV = hasUDA!(value!(C, m), T); 49 } 50 51 /** 52 * Wrapper around hasUDA!(...) 53 */ 54 template hasUDAV(C, alias m, alias t) 55 { 56 alias hasUDAV = hasUDA!(value!(C, m), t); 57 } 58 59 /** 60 * Wrapper around hasUDA!(...) 61 */ 62 template hasUDAV(alias c, alias m, alias t) 63 { 64 alias hasUDAV = hasUDA!(value!(c, m), t); 65 } 66 67 /** 68 * Checks if given template has a parameter attribute. 69 */ 70 template hasParameter(alias E) 71 { 72 alias hasParameter = Alias!(hasUDA!(E, Parameter)); 73 } 74 75 /** 76 * Checks if given template has a parameter attribute. 77 */ 78 template hasParameter(C, alias E) 79 { 80 alias hasParameter = Alias!(hasUDA!(value!(C, E), Parameter)); 81 } 82 83 /** 84 * Checks if the given struct has a short parameter. 85 * Params: 86 * parameter The short flag that the parameter should have. 87 */ 88 bool hasShortParameter(C)(dchar parameter) 89 { 90 static foreach (member; __traits(allMembers, C)) 91 { 92 static if (hasParameter!(member) && getParameter!(member).shortName == parameter) 93 { 94 return true; 95 } 96 } 97 98 return false; 99 } 100 101 /** 102 * Checks if the given struct has a long parameter. 103 * Params: 104 * parameter The long flag that the parameter should have. 105 */ 106 bool hasLongParameter(C)(string parameter) 107 { 108 static foreach (member; __traits(allMembers, C)) 109 { 110 if (hasParameter!(C, member) && getParameter!(C, member).longName == parameter) 111 return true; 112 } 113 return false; 114 } 115 116 /** 117 * Gets the parameter attribute connected to an element. 118 */ 119 template getParameter(alias E) 120 { 121 alias getParameter = Alias!(getUDAs!(E, Parameter)[0]); 122 } 123 124 /** 125 * Gets the parameter attribute connected to an element. 126 */ 127 template getParameter(C, alias e) 128 { 129 alias getParameter = Alias!(getUDAs!(value!(C, e), Parameter)[0]); 130 } 131 132 /** 133 * Checks if the element has a description attribute. 134 */ 135 template hasDescription(alias E) 136 { 137 alias hasDescription = Alias!(hasUDA!(E, Description)); 138 } 139 140 /** 141 * Gets the description attribute of an element. 142 */ 143 template getDescription(alias E) 144 { 145 alias getDescription = Alias!(getUDAs!(E, Description)[0]); 146 } 147 148 /** 149 * Checks if a given parameter is required. 150 */ 151 template isRequired(alias E) 152 { 153 alias isRequired = Alias!(hasUDA!(E, Required)); 154 } 155 156 /** 157 * Checks if a given parameter is required. 158 */ 159 template isRequired(C, alias e) 160 { 161 alias isRequired = Alias!(isRequired!(value!(C, e))); 162 } 163 164 /** 165 * Checks if a given parameter is a named parameter. 166 */ 167 template isNamedParameter(alias e) 168 { 169 alias isNamedParameter = Alias!(getParameter!(e).longName.length > 0); 170 } 171 172 /** 173 * Checks if a given parameter is a named parameter. 174 */ 175 template isNamedParameter(alias C, alias e) 176 { 177 alias isNamedParameter = isNamedParameter!(value!(C, e)); 178 } 179 180 /** 181 * Checks if a given parameter is an unnamed parameter. 182 */ 183 template isUnnamedParameter(alias C, alias e) 184 { 185 alias isUnnamedParameter = Alias!(hasParameter!(value!(C, e)) && !isNamedParameter!(C, e)); 186 } 187 188 private template hasNamedParameters(C, members...) 189 { 190 static if (isNamedParameter!(C, members[0])) 191 alias hasNamedParameters = Alias!true; 192 else static if (members.length == 1) 193 alias hasNamedParameters = isNamedParameter!(C, members[0]); 194 else 195 alias hasNamedParameters = hasNamedParameters!(C, members[1 .. $]); 196 } 197 198 private template hasNamedParameters(C, member) 199 { 200 alias hasNamedParameters = isNamedParameter!(C, members[i]); 201 } 202 203 /** 204 * Checks if the struct has a named parameter. 205 */ 206 alias hasNamedParameters(C) = hasNamedParameters!(C, __traits(allMembers, C)); 207 208 private template hasUnnamedParameters(C, members...) 209 { 210 static if (!isNamedParameter!(C, members[0])) 211 alias hasUnnamedParameters = Alias!true; 212 else static if (members.length == 1) 213 alias hasUnnamedParameters = Alias!(!isNamedParameter!(C, members[0])); 214 else 215 alias hasUnnamedParameters = hasUnnamedParameters!(C, members[1 .. $]); 216 } 217 218 /** 219 * Checks if the struct has an unamed parameter. 220 */ 221 alias hasUnnamedParameters(C) = hasUnnamedParameters!(C, __traits(allMembers, C)); 222 223 /* 224 private template getUnnamedParameters(C) 225 { 226 import std.algorithm.iteration : filter; 227 228 alias getUnnamedParameters = Alias!(__traits(allMembers, C).filter!(b => !isNamedParameter(b))); 229 } 230 */