| ... | @@ -408,104 +408,127 @@ fn createChildOnly( | ... | @@ -408,104 +408,127 @@ fn createChildOnly( |
| 408 | return child; | 408 | return child; |
| 409 | } | 409 | } |
| 410 | | 410 | |
| 411 | fn userInputOptionsFromArgs(allocator: Allocator, args: anytype) UserInputOptionsMap { | 411 | fn userInputOptionsFromArgs(arena: Allocator, args: anytype) UserInputOptionsMap { |
| 412 | var user_input_options = UserInputOptionsMap.init(allocator); | 412 | var map = UserInputOptionsMap.init(arena); |
| 413 | inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| { | 413 | inline for (@typeInfo(@TypeOf(args)).@"struct".fields) |field| { |
| 414 | const v = @field(args, field.name); | 414 | if (field.type == @Type(.null)) continue; |
| 415 | const T = @TypeOf(v); | 415 | addUserInputOptionFromArg(arena, &map, field, field.type, @field(args, field.name)); |
| 416 | switch (T) { | 416 | } |
| 417 | Target.Query => { | 417 | return map; |
| 418 | user_input_options.put(field.name, .{ | 418 | } |
| 419 | .name = field.name, | 419 | |
| 420 | .value = .{ .scalar = v.zigTriple(allocator) catch @panic("OOM") }, | 420 | fn addUserInputOptionFromArg( |
| 421 | .used = false, | 421 | arena: Allocator, |
| 422 | }) catch @panic("OOM"); | 422 | map: *UserInputOptionsMap, |
| 423 | user_input_options.put("cpu", .{ | 423 | field: std.builtin.Type.StructField, |
| 424 | .name = "cpu", | 424 | comptime T: type, |
| 425 | .value = .{ .scalar = v.serializeCpuAlloc(allocator) catch @panic("OOM") }, | 425 | /// If null, the value won't be added, but `T` will still be type-checked. |
| 426 | .used = false, | 426 | maybe_value: ?T, |
| 427 | }) catch @panic("OOM"); | 427 | ) void { |
| 428 | }, | 428 | switch (T) { |
| 429 | ResolvedTarget => { | 429 | Target.Query => return if (maybe_value) |v| { |
| 430 | user_input_options.put(field.name, .{ | 430 | map.put(field.name, .{ |
| 431 | .name = field.name, | 431 | .name = field.name, |
| 432 | .value = .{ .scalar = v.query.zigTriple(allocator) catch @panic("OOM") }, | 432 | .value = .{ .scalar = v.zigTriple(arena) catch @panic("OOM") }, |
| 433 | .used = false, | 433 | .used = false, |
| 434 | }) catch @panic("OOM"); | 434 | }) catch @panic("OOM"); |
| 435 | user_input_options.put("cpu", .{ | 435 | map.put("cpu", .{ |
| 436 | .name = "cpu", | 436 | .name = "cpu", |
| 437 | .value = .{ .scalar = v.query.serializeCpuAlloc(allocator) catch @panic("OOM") }, | 437 | .value = .{ .scalar = v.serializeCpuAlloc(arena) catch @panic("OOM") }, |
| 438 | .used = false, | 438 | .used = false, |
| 439 | }) catch @panic("OOM"); | 439 | }) catch @panic("OOM"); |
| 440 | }, | 440 | }, |
| 441 | LazyPath => { | 441 | ResolvedTarget => return if (maybe_value) |v| { |
| 442 | user_input_options.put(field.name, .{ | 442 | map.put(field.name, .{ |
| | 443 | .name = field.name, |
| | 444 | .value = .{ .scalar = v.query.zigTriple(arena) catch @panic("OOM") }, |
| | 445 | .used = false, |
| | 446 | }) catch @panic("OOM"); |
| | 447 | map.put("cpu", .{ |
| | 448 | .name = "cpu", |
| | 449 | .value = .{ .scalar = v.query.serializeCpuAlloc(arena) catch @panic("OOM") }, |
| | 450 | .used = false, |
| | 451 | }) catch @panic("OOM"); |
| | 452 | }, |
| | 453 | LazyPath => return if (maybe_value) |v| { |
| | 454 | map.put(field.name, .{ |
| | 455 | .name = field.name, |
| | 456 | .value = .{ .lazy_path = v.dupeInner(arena) }, |
| | 457 | .used = false, |
| | 458 | }) catch @panic("OOM"); |
| | 459 | }, |
| | 460 | []const LazyPath => return if (maybe_value) |v| { |
| | 461 | var list = ArrayList(LazyPath).initCapacity(arena, v.len) catch @panic("OOM"); |
| | 462 | for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(arena)); |
| | 463 | map.put(field.name, .{ |
| | 464 | .name = field.name, |
| | 465 | .value = .{ .lazy_path_list = list }, |
| | 466 | .used = false, |
| | 467 | }) catch @panic("OOM"); |
| | 468 | }, |
| | 469 | []const u8 => return if (maybe_value) |v| { |
| | 470 | map.put(field.name, .{ |
| | 471 | .name = field.name, |
| | 472 | .value = .{ .scalar = v }, |
| | 473 | .used = false, |
| | 474 | }) catch @panic("OOM"); |
| | 475 | }, |
| | 476 | []const []const u8 => return if (maybe_value) |v| { |
| | 477 | var list = ArrayList([]const u8).initCapacity(arena, v.len) catch @panic("OOM"); |
| | 478 | list.appendSliceAssumeCapacity(v); |
| | 479 | map.put(field.name, .{ |
| | 480 | .name = field.name, |
| | 481 | .value = .{ .list = list }, |
| | 482 | .used = false, |
| | 483 | }) catch @panic("OOM"); |
| | 484 | }, |
| | 485 | else => switch (@typeInfo(T)) { |
| | 486 | .bool => return if (maybe_value) |v| { |
| | 487 | map.put(field.name, .{ |
| 443 | .name = field.name, | 488 | .name = field.name, |
| 444 | .value = .{ .lazy_path = v.dupeInner(allocator) }, | 489 | .value = .{ .scalar = if (v) "true" else "false" }, |
| 445 | .used = false, | 490 | .used = false, |
| 446 | }) catch @panic("OOM"); | 491 | }) catch @panic("OOM"); |
| 447 | }, | 492 | }, |
| 448 | []const LazyPath => { | 493 | .@"enum", .enum_literal => return if (maybe_value) |v| { |
| 449 | var list = ArrayList(LazyPath).initCapacity(allocator, v.len) catch @panic("OOM"); | 494 | map.put(field.name, .{ |
| 450 | for (v) |lp| list.appendAssumeCapacity(lp.dupeInner(allocator)); | | |
| 451 | user_input_options.put(field.name, .{ | | |
| 452 | .name = field.name, | 495 | .name = field.name, |
| 453 | .value = .{ .lazy_path_list = list }, | 496 | .value = .{ .scalar = @tagName(v) }, |
| 454 | .used = false, | 497 | .used = false, |
| 455 | }) catch @panic("OOM"); | 498 | }) catch @panic("OOM"); |
| 456 | }, | 499 | }, |
| 457 | []const u8 => { | 500 | .comptime_int, .int => return if (maybe_value) |v| { |
| 458 | user_input_options.put(field.name, .{ | 501 | map.put(field.name, .{ |
| 459 | .name = field.name, | 502 | .name = field.name, |
| 460 | .value = .{ .scalar = v }, | 503 | .value = .{ .scalar = std.fmt.allocPrint(arena, "{d}", .{v}) catch @panic("OOM") }, |
| 461 | .used = false, | 504 | .used = false, |
| 462 | }) catch @panic("OOM"); | 505 | }) catch @panic("OOM"); |
| 463 | }, | 506 | }, |
| 464 | []const []const u8 => { | 507 | .comptime_float, .float => return if (maybe_value) |v| { |
| 465 | var list = ArrayList([]const u8).initCapacity(allocator, v.len) catch @panic("OOM"); | 508 | map.put(field.name, .{ |
| 466 | list.appendSliceAssumeCapacity(v); | | |
| 467 | | | |
| 468 | user_input_options.put(field.name, .{ | | |
| 469 | .name = field.name, | 509 | .name = field.name, |
| 470 | .value = .{ .list = list }, | 510 | .value = .{ .scalar = std.fmt.allocPrint(arena, "{e}", .{v}) catch @panic("OOM") }, |
| 471 | .used = false, | 511 | .used = false, |
| 472 | }) catch @panic("OOM"); | 512 | }) catch @panic("OOM"); |
| 473 | }, | 513 | }, |
| 474 | else => switch (@typeInfo(T)) { | 514 | .null => unreachable, |
| 475 | .bool => { | 515 | .optional => |info| switch (@typeInfo(info.child)) { |
| 476 | user_input_options.put(field.name, .{ | 516 | .optional => {}, |
| 477 | .name = field.name, | 517 | else => { |
| 478 | .value = .{ .scalar = if (v) "true" else "false" }, | 518 | addUserInputOptionFromArg( |
| 479 | .used = false, | 519 | arena, |
| 480 | }) catch @panic("OOM"); | 520 | map, |
| 481 | }, | 521 | field, |
| 482 | .@"enum", .enum_literal => { | 522 | info.child, |
| 483 | user_input_options.put(field.name, .{ | 523 | maybe_value orelse null, |
| 484 | .name = field.name, | 524 | ); |
| 485 | .value = .{ .scalar = @tagName(v) }, | 525 | return; |
| 486 | .used = false, | | |
| 487 | }) catch @panic("OOM"); | | |
| 488 | }, | | |
| 489 | .comptime_int, .int => { | | |
| 490 | user_input_options.put(field.name, .{ | | |
| 491 | .name = field.name, | | |
| 492 | .value = .{ .scalar = std.fmt.allocPrint(allocator, "{d}", .{v}) catch @panic("OOM") }, | | |
| 493 | .used = false, | | |
| 494 | }) catch @panic("OOM"); | | |
| 495 | }, | 526 | }, |
| 496 | .comptime_float, .float => { | | |
| 497 | user_input_options.put(field.name, .{ | | |
| 498 | .name = field.name, | | |
| 499 | .value = .{ .scalar = std.fmt.allocPrint(allocator, "{e}", .{v}) catch @panic("OOM") }, | | |
| 500 | .used = false, | | |
| 501 | }) catch @panic("OOM"); | | |
| 502 | }, | | |
| 503 | else => @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(T)), | | |
| 504 | }, | 527 | }, |
| 505 | } | 528 | else => {}, |
| | 529 | }, |
| 506 | } | 530 | } |
| 507 | | 531 | @compileError("option '" ++ field.name ++ "' has unsupported type: " ++ @typeName(field.type)); |
| 508 | return user_input_options; | | |
| 509 | } | 532 | } |
| 510 | | 533 | |
| 511 | const OrderedUserValue = union(enum) { | 534 | const OrderedUserValue = union(enum) { |