From 6dd4d5d28daec96ed0fb6160bc37afff8e430263 Mon Sep 17 00:00:00 2001 From: Richard Feldman Date: Sun, 27 Jul 2025 12:36:24 -0400 Subject: [PATCH] Introduce CompactWriter.deinit() --- src/base/Ident.zig | 12 +++---- src/base/SmallStringInterner.zig | 17 +++++---- src/collections/safe_list.zig | 36 +++++++++---------- src/serialization/CompactWriter.zig | 7 +++- .../test/compact_writer_test.zig | 14 ++++---- 5 files changed, 45 insertions(+), 41 deletions(-) diff --git a/src/base/Ident.zig b/src/base/Ident.zig index 67ac1016cd..cbea3c9981 100644 --- a/src/base/Ident.zig +++ b/src/base/Ident.zig @@ -370,7 +370,7 @@ test "Ident.Store empty CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -432,7 +432,7 @@ test "Ident.Store basic CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -500,7 +500,7 @@ test "Ident.Store with genUnique CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -560,7 +560,7 @@ test "Ident.Store frozen state CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -637,7 +637,7 @@ test "Ident.Store comprehensive CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -710,7 +710,7 @@ test "Ident.Store multiple stores CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try store1.serialize(gpa, &writer); const offset1 = writer.total_bytes - @sizeOf(Store); diff --git a/src/base/SmallStringInterner.zig b/src/base/SmallStringInterner.zig index af22ee6824..7ad05e6070 100644 --- a/src/base/SmallStringInterner.zig +++ b/src/base/SmallStringInterner.zig @@ -115,9 +115,9 @@ pub fn serialize( allocator: std.mem.Allocator, writer: *collections.CompactWriter, ) std.mem.Allocator.Error!*const Self { - // First, write the struct with an empty hash map + // First, write the struct const offset_self = try writer.appendAlloc(allocator, Self); - + // Then serialize the bytes SafeList and update the struct offset_self.* = .{ .bytes = (try self.bytes.serialize(allocator, writer)).*, @@ -131,7 +131,6 @@ pub fn serialize( /// Add the given offset to the memory addresses of all pointers in `self`. pub fn relocate(self: *Self, offset: isize) void { - // Relocate the bytes SafeList self.bytes.relocate(offset); // The strings hash map is always empty after deserialization, @@ -158,7 +157,7 @@ test "SmallStringInterner empty CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -227,7 +226,7 @@ test "SmallStringInterner basic CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -300,7 +299,7 @@ test "SmallStringInterner with populated hashmap CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -369,7 +368,7 @@ test "SmallStringInterner frozen state CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -439,7 +438,7 @@ test "SmallStringInterner edge cases CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -505,7 +504,7 @@ test "SmallStringInterner multiple interners CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try interner1.serialize(gpa, &writer); const offset1 = writer.total_bytes - @sizeOf(Self); diff --git a/src/collections/safe_list.zig b/src/collections/safe_list.zig index 6ef2bf1d8a..7fc09d1e97 100644 --- a/src/collections/safe_list.zig +++ b/src/collections/safe_list.zig @@ -1369,7 +1369,7 @@ test "SafeList(u32) CompactWriter roundtrip with file" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -1428,7 +1428,7 @@ test "SafeList(struct) CompactWriter roundtrip with file" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -1476,7 +1476,7 @@ test "SafeList empty list CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -1539,7 +1539,7 @@ test "SafeList empty lists CompactWriter roundtrip multiple types" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try list1.serialize(gpa, &writer); const offset1 = writer.total_bytes - @sizeOf(SafeList(T)); @@ -1598,7 +1598,7 @@ test "SafeList CompactWriter verify offset calculation" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); const serialized_ptr = try list.serialize(gpa, &writer); @@ -1631,7 +1631,7 @@ test "SafeList CompactWriter complete roundtrip example" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); // Step 3: Serialize - this writes data first, then the SafeList struct const serialized_ptr = try original.serialize(gpa, &writer); @@ -1719,7 +1719,7 @@ test "SafeList CompactWriter multiple lists with different alignments" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); // Serialize all lists and track their positions const ptr_u8 = try list_u8.serialize(gpa, &writer); @@ -1815,7 +1815,7 @@ test "SafeList CompactWriter interleaved pattern with alignment tracking" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); // Track offsets as we go var offsets = std.ArrayList(usize).init(gpa); @@ -1964,7 +1964,7 @@ test "SafeList CompactWriter brute-force alignment verification" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); // Serialize in pattern: list1, u8 list, list2 // This tests alignment padding between different types @@ -2055,7 +2055,7 @@ test "SafeMultiList CompactWriter roundtrip with file" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -2122,7 +2122,7 @@ test "SafeMultiList empty list CompactWriter roundtrip" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -2192,7 +2192,7 @@ test "SafeMultiList CompactWriter multiple lists different alignments" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); // Serialize all lists _ = try list1.serialize(gpa, &writer); @@ -2272,7 +2272,7 @@ test "SafeMultiList CompactWriter field access after deserialization" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); @@ -2369,7 +2369,7 @@ test "SafeMultiList CompactWriter brute-force alignment verification" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try list.serialize(gpa, &writer); const offset1 = writer.total_bytes - @sizeOf(SafeMultiList(TestType)); @@ -2467,7 +2467,7 @@ test "SafeMultiList CompactWriter various field alignments and sizes" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try list.serialize(gpa, &writer); try writer.writeGather(gpa, file); @@ -2567,7 +2567,7 @@ test "SafeMultiList CompactWriter verify exact memory layout" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try original.serialize(gpa, &writer); try writer.writeGather(gpa, file); @@ -2658,7 +2658,7 @@ test "SafeMultiList CompactWriter stress test many field types" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try list.serialize(gpa, &writer); try writer.writeGather(gpa, file); @@ -2727,7 +2727,7 @@ test "SafeMultiList CompactWriter empty with capacity" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(gpa); + defer writer.deinit(gpa); _ = try list.serialize(gpa, &writer); try writer.writeGather(gpa, file); diff --git a/src/serialization/CompactWriter.zig b/src/serialization/CompactWriter.zig index cfd00881a5..7ed924e0ff 100644 --- a/src/serialization/CompactWriter.zig +++ b/src/serialization/CompactWriter.zig @@ -125,7 +125,7 @@ pub const CompactWriter = struct { try self.padToAlignment(allocator, alignment); const offset = self.total_bytes; - + try self.iovecs.append(allocator, .{ .iov_base = @ptrCast(@as([*]const u8, @ptrCast(slice.ptr))), .iov_len = size * len, @@ -170,6 +170,11 @@ pub const CompactWriter = struct { return buffer[0..self.total_bytes]; } + + /// Deinitialize the CompactWriter, freeing all allocated memory + pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void { + self.iovecs.deinit(allocator); + } }; const Iovec = extern struct { diff --git a/src/serialization/test/compact_writer_test.zig b/src/serialization/test/compact_writer_test.zig index d585fd9d8a..b5969f0baa 100644 --- a/src/serialization/test/compact_writer_test.zig +++ b/src/serialization/test/compact_writer_test.zig @@ -15,7 +15,7 @@ test "CompactWriter basic functionality" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // Test appendAlloc const test_struct = struct { @@ -44,7 +44,7 @@ test "CompactWriter appendSlice" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // Create some test data const data = [_]u32{ 1, 2, 3, 4, 5 }; @@ -67,7 +67,7 @@ test "CompactWriter alignment padding" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // First append a u8 (1-byte aligned) const byte_ptr = try writer.appendAlloc(allocator, u8); @@ -94,7 +94,7 @@ test "CompactWriter multiple allocations" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // Append multiple items const item1 = try writer.appendAlloc(allocator, u64); @@ -123,7 +123,7 @@ test "CompactWriter up-front padding with various alignments" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // Start with u8 (1-byte aligned) _ = try writer.appendAlloc(allocator, u8); @@ -162,7 +162,7 @@ test "CompactWriter slice alignment" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // Start with a u8 _ = try writer.appendAlloc(allocator, u8); @@ -200,7 +200,7 @@ test "CompactWriter brute-force appendSlice alignment" { .iovecs = .{}, .total_bytes = 0, }; - defer writer.iovecs.deinit(allocator); + defer writer.deinit(allocator); // Create test data var data: [8]T = undefined;