From dafc69726ffbe13213cc31891455f046c9a9a430 Mon Sep 17 00:00:00 2001 From: Emil Lerch Date: Fri, 29 Aug 2025 15:00:27 -0700 Subject: [PATCH] handle http headers with value lists --- .pre-commit-config.yaml | 17 +++++++---------- src/aws.zig | 25 +++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f72a8b5..8e6ed25 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -15,19 +15,16 @@ repos: - id: zig-build - repo: local hooks: - - id: zlint + - id: smoke-test name: Run zig build smoke-test entry: zig args: ["build", "--verbose", "smoke-test"] language: system types: [file] pass_filenames: false - - # - repo: local - # hooks: - # - id: zlint - # name: Run zlint - # entry: zlint - # args: ["--deny-warnings", "--fix"] - # language: system - # types: [zig] + - id: zlint + name: Run zlint + entry: zlint + args: ["--deny-warnings", "--fix"] + language: system + types: [zig] diff --git a/src/aws.zig b/src/aws.zig index 5fb8791..f764cce 100644 --- a/src/aws.zig +++ b/src/aws.zig @@ -888,6 +888,8 @@ fn parseInt(comptime T: type, val: []const u8) !T { return rc; } +/// generalAllocPrint is specific to http headers, which are documented +/// at https://smithy.io/2.0/spec/http-bindings.html#httpheader-trait fn generalAllocPrint(allocator: std.mem.Allocator, val: anytype) !?[]const u8 { const T = @TypeOf(val); switch (@typeInfo(T)) { @@ -898,6 +900,29 @@ fn generalAllocPrint(allocator: std.mem.Allocator, val: anytype) !?[]const u8 { .one => return try std.fmt.allocPrint(allocator, "{s}", .{val}), .many => return try std.fmt.allocPrint(allocator, "{s}", .{val}), .slice => { + if (T == [][]const u8) { + // This would be a list type, which is the described on the first bullet + // of httpHeader trait serialization rules. An example can be found + // in S3 ListObjects API (see the OptionalObjectAttributes property) + // https://smithy.io/2.0/spec/http-bindings.html#serialization-rules + // + // S3 ListObjects REST API: https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html + // + // This also applies to v2, but I don't have usage example here, we're just + // following the spec + // + // tl;dr below, we're putting commas between values + // + // TODO: we need a unit test for this + var vals_len: usize = 0; + for (val, 0..) |v, i| vals_len += v.len + if (i + 1 < v.len) @as(usize, 1) else @as(usize, 0); + var aw = try std.Io.Writer.Allocating.initCapacity(allocator, vals_len); + defer aw.deinit(); + const writer = &aw.writer; + for (val, 0..) |v, i| + try writer.print("{s}{s}", .{ v, if (i + 1 < v.len) "," else "" }); // change v to val to trigger compile error (when unit test is written) + return try aw.toOwnedSlice(); + } return try std.fmt.allocPrint(allocator, "{s}", .{val}); }, .c => return try std.fmt.allocPrint(allocator, "{s}", .{val}),