@@ -9,7 +9,7 @@ pub const CliError = error{ InvalidArg, InvalidNumberOfArgs, CliArgumentNotFound
9
9
const ArgMetadata = struct {
10
10
key : []const u8 ,
11
11
value : []const u8 ,
12
- comptime typ : std.builtin.Type = type ,
12
+ comptime typ : type = type ,
13
13
optional : bool ,
14
14
};
15
15
@@ -126,17 +126,17 @@ pub fn Snek(comptime CliInterface: type) type {
126
126
};
127
127
128
128
unwrap_for : inline for (cli_reflected .Struct .fields ) | field | {
129
- const arg = self .arg_metadata .get (field .name );
129
+ const arg = self .arg_metadata .get (field .name ) orelse null ;
130
130
131
131
// If arg does NOT exist and the field is NOT optional, its an error case, so handle accordingly
132
- if (! arg ) {
132
+ if (arg == null ) {
133
133
switch (@typeInfo (field .type )) {
134
134
.Optional = > {
135
- continue :unwrap_for ;
135
+ break :unwrap_for ;
136
136
},
137
137
else = > {
138
138
// Check if there is a default value, if there is, move on (same case as an optional). Else, error case
139
- if (field .default_value ) continue :unwrap_for ;
139
+ if (field .default_value == null ) break :unwrap_for ;
140
140
141
141
std .debug .print ("Required arugment {s} was not found in CLI flags. Check -help menu for required flags" , .{field .name });
142
142
return CliError .RequiredArgumentNotFound ;
@@ -184,6 +184,10 @@ pub fn Snek(comptime CliInterface: type) type {
184
184
// Skip first line, its always the name of the calling function
185
185
_ = args .skip ();
186
186
187
+ const interface : CliInterface = undefined ;
188
+
189
+ const cli_reflected = @typeInfo (@TypeOf (interface ));
190
+
187
191
while (args .next ()) | arg | {
188
192
if (arg [0 ] != '-' ) {
189
193
return CliError .InvalidCommand ;
@@ -213,33 +217,34 @@ pub fn Snek(comptime CliInterface: type) type {
213
217
}
214
218
215
219
// No struct field of this name was found. Send error instead of moving on
216
- if (! @hasField (CliInterface , arg_key_d )) return CliError .InvalidCommand ;
220
+ if (! self .hasKey (arg_key_d )) return CliError .InvalidCommand ;
221
+
222
+ var is_optional : bool = false ;
223
+ comptime var typ : type = undefined ;
224
+ inline for (cli_reflected .Struct .fields ) | field | {
225
+ switch (@typeInfo (field .type )) {
226
+ .Optional = > {
227
+ is_optional = true ;
228
+ },
229
+ else = > {
230
+ typ = @TypeOf (field .type );
231
+ },
232
+ }
233
+ }
217
234
218
235
// .typ is used to eventually switch when we marshal the type of the value into the struct field
219
- try self .arg_metadata .put (arg_key_d , .{ .key = arg_key_d , .value = std .mem .trim (u8 , arg_val_d , " " ), .optional = self . isOptional ( arg_key_d ) , .typ = extractTypeInfoFromKey ( arg_key_d ) });
236
+ try self .arg_metadata .put (arg_key_d , .{ .key = arg_key_d , .value = std .mem .trim (u8 , arg_val_d , " " ), .optional = is_optional , .typ = typ });
220
237
}
221
238
}
222
239
223
- fn extractTypeInfoFromKey (key : []const u8 ) std.builtin.Type {
224
- const s_enum = std .meta .stringToEnum (CliInterface , key );
225
-
226
- // We assume that the field is already found since it passed the hasKey check. So we do *not* handle the null case.
227
- const field_info = std .meta .fieldInfo (CliInterface , s_enum .? );
228
-
229
- return @typeInfo (field_info );
230
- }
231
-
232
- fn isOptional (self : * Self , key : []const u8 ) bool {
240
+ fn hasKey (self : * Self , key : []const u8 ) bool {
233
241
_ = self ;
234
242
235
- switch (extractTypeInfoFromKey (key )) {
236
- .Optional = > {
237
- return true ;
238
- },
239
- else = > {
240
- return false ;
241
- },
243
+ inline for (std .meta .fields (CliInterface )) | field | {
244
+ if (std .mem .eql (u8 , key , field .name )) return true ;
242
245
}
246
+
247
+ return false ;
243
248
}
244
249
245
250
// Ensures passed in value is a struct. It cannot be anything else so strict checking is applied to public functions
0 commit comments