diff --git a/src/aws.zig b/src/aws.zig index 1d735f0..3b40e7a 100644 --- a/src/aws.zig +++ b/src/aws.zig @@ -858,15 +858,7 @@ fn FullResponse(comptime action: anytype) type { const Response = @TypeOf(self.response); if (@hasDecl(Response, "http_header")) { inline for (std.meta.fields(@TypeOf(Response.http_header))) |f| { - const field_type = @TypeOf(@field(self.response, f.name)); - // TODO: Fix this. We need to make this much more robust - // The deal is we have to do the dupe though - // Also, this is a memory leak atm - if (@typeInfo(field_type) == .Optional) { - if (@field(self.response, f.name) != null) { - self.allocator.free(@field(self.response, f.name).?); - } - } + safeFree(self.allocator, @field(self.response, f.name)); } } if (@hasDecl(Response, "http_payload")) { @@ -883,6 +875,13 @@ fn FullResponse(comptime action: anytype) type { } }; } +fn safeFree(allocator: std.mem.Allocator, obj: anytype) void { + switch (@typeInfo(@TypeOf(obj))) { + .Pointer => allocator.free(obj), + .Optional => if (obj) |o| safeFree(allocator, o), + else => {}, + } +} fn queryFieldTransformer(allocator: std.mem.Allocator, field_name: []const u8, options: url.EncodingOptions) anyerror![]const u8 { _ = options; return try case.snakeToPascal(allocator, field_name); diff --git a/src/main.zig b/src/main.zig index 2f8cf96..5c0055c 100644 --- a/src/main.zig +++ b/src/main.zig @@ -238,7 +238,6 @@ pub fn main() anyerror!void { // that frees both a bool and an i64 std.log.err("This demo (rest_xml_work_with_s3) is not yet fully functional in 0.11", .{}); const key = "i/am/a/teapot/foo"; - _ = key; // // const key = "foo"; // const bucket = blk: { @@ -266,43 +265,39 @@ pub fn main() anyerror!void { .region = location, .client = client, }; - // TODO: This block triggers the free(bool) problem. Note that the rest of this will have runtime issues - // without the block - // { - // const result = try aws.Request(services.s3.put_object).call(.{ - // .bucket = bucket, - // .key = key, - // .content_type = "text/plain", - // .body = "bar", - // .storage_class = "STANDARD", - // }, s3opts); - // std.log.info("PutObject Request id: {any}", .{result.response_metadata.request_id}); - // std.log.info("PutObject etag: {any}", .{result.response.e_tag.?}); - // defer result.deinit(); - // } - // TODO: This block triggers both compile errors - // { - // // Note that boto appears to redirect by default, but java - // // does not. We will not - // const result = try aws.Request(services.s3.get_object).call(.{ - // .bucket = bucket, - // .key = key, - // }, s3opts); - // std.log.info("GetObject Request id: {any}", .{result.response_metadata.request_id}); - // std.log.info("GetObject Body: {any}", .{result.response.body}); - // std.log.info("GetObject etag: {any}", .{result.response.e_tag.?}); - // std.log.info("GetObject last modified (seconds since epoch): {d}", .{result.response.last_modified.?}); - // defer result.deinit(); - // } - // TODO: This block triggers the free(bool) problem. Note that the rest of this will have runtime issues - // { - // const result = try aws.Request(services.s3.delete_object).call(.{ - // .bucket = bucket, - // .key = key, - // }, s3opts); - // std.log.info("DeleteObject Request id: {any}", .{result.response_metadata.request_id}); - // defer result.deinit(); - // } + { + const result = try aws.Request(services.s3.put_object).call(.{ + .bucket = bucket, + .key = key, + .content_type = "text/plain", + .body = "bar", + .storage_class = "STANDARD", + }, s3opts); + std.log.info("PutObject Request id: {any}", .{result.response_metadata.request_id}); + std.log.info("PutObject etag: {any}", .{result.response.e_tag.?}); + defer result.deinit(); + } + { + // Note that boto appears to redirect by default, but java + // does not. We will not + const result = try aws.Request(services.s3.get_object).call(.{ + .bucket = bucket, + .key = key, + }, s3opts); + std.log.info("GetObject Request id: {any}", .{result.response_metadata.request_id}); + std.log.info("GetObject Body: {any}", .{result.response.body}); + std.log.info("GetObject etag: {any}", .{result.response.e_tag.?}); + std.log.info("GetObject last modified (seconds since epoch): {d}", .{result.response.last_modified.?}); + defer result.deinit(); + } + { + const result = try aws.Request(services.s3.delete_object).call(.{ + .bucket = bucket, + .key = key, + }, s3opts); + std.log.info("DeleteObject Request id: {any}", .{result.response_metadata.request_id}); + defer result.deinit(); + } { const result = try aws.Request(services.s3.list_objects).call(.{ .bucket = bucket,