Skip to content

Commit d263275

Browse files
committed
Allow parsers to take parser allocator as parameter
1 parent a4e784d commit d263275

1 file changed

Lines changed: 45 additions & 6 deletions

File tree

clap.zig

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -770,15 +770,16 @@ pub fn parseEx(
770770

771771
const parser = comptime switch (param.takes_value) {
772772
.none => null,
773-
.one, .many => @field(value_parsers, param.id.value()),
773+
.one, .many => withAllocatorParser(@field(value_parsers, param.id.value())),
774774
};
775775

776776
const name = longest.name[0..longest.name.len].*;
777+
777778
switch (param.takes_value) {
778779
.none => @field(arguments, &name) +|= 1,
779-
.one => @field(arguments, &name) = try parser(arg.value.?),
780+
.one => @field(arguments, &name) = try parser(arg.value.?, allocator),
780781
.many => {
781-
const value = try parser(arg.value.?);
782+
const value = try parser(arg.value.?, allocator);
782783
try @field(arguments, &name).append(allocator, value);
783784
},
784785
}
@@ -801,7 +802,7 @@ pub fn parseEx(
801802

802803
const parser = comptime switch (param.takes_value) {
803804
.none => null,
804-
.one, .many => @field(value_parsers, param.id.value()),
805+
.one, .many => withAllocatorParser(@field(value_parsers, param.id.value())),
805806
};
806807

807808
// We keep track of how many positionals we have received. This is used to pick which
@@ -811,8 +812,8 @@ pub fn parseEx(
811812
const last = positionals.len == i + 1;
812813
if ((last and positional_count >= i) or positional_count == i) {
813814
switch (@typeInfo(@TypeOf(pos.*))) {
814-
.optional => pos.* = try parser(arg.value.?),
815-
else => try pos.append(allocator, try parser(arg.value.?)),
815+
.optional => pos.* = try parser(arg.value.?, allocator),
816+
else => try pos.append(allocator, try parser(arg.value.?, allocator)),
816817
}
817818

818819
if (opt.terminating_positional <= positional_count)
@@ -852,6 +853,44 @@ pub fn parseEx(
852853
};
853854
}
854855

856+
fn AllocatorParserReturnType(parser: anytype) type {
857+
const parser_info = switch (@typeInfo(@TypeOf(parser))) {
858+
.@"fn" => |info| info,
859+
else => {
860+
return void;
861+
},
862+
};
863+
return parser_info.return_type orelse void;
864+
}
865+
866+
fn AllocatorParser(parser: anytype) type {
867+
return fn (value: anytype, allocator: std.mem.Allocator) AllocatorParserReturnType(parser);
868+
}
869+
870+
pub fn withAllocatorParser(parser: anytype) AllocatorParser(parser) {
871+
const parser_info = switch (@typeInfo(@TypeOf(parser))) {
872+
.@"fn" => |info| info,
873+
else => {
874+
@compileError("withAllocatorParser() must be called with a non-null parser implementation");
875+
},
876+
};
877+
return struct {
878+
pub fn parseWithAllocator(value: anytype, allocator: std.mem.Allocator) AllocatorParserReturnType(parser) {
879+
switch (parser_info.params.len) {
880+
2 => {
881+
return parser(value, allocator);
882+
},
883+
1 => {
884+
return parser(value);
885+
},
886+
else => {
887+
return error.InvalidArgumentParser;
888+
},
889+
}
890+
}
891+
}.parseWithAllocator;
892+
}
893+
855894
/// The result of `parseEx`. Is owned by the caller and should be freed with `deinit`.
856895
pub fn ResultEx(
857896
comptime Id: type,

0 commit comments

Comments
 (0)