@@ -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`.
856895pub fn ResultEx (
857896 comptime Id : type ,
0 commit comments