Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions src/tests.zig
Original file line number Diff line number Diff line change
Expand Up @@ -2574,6 +2574,57 @@ test "utils.List dynamic-item: offsets decrease" {
try expectError(error.OffsetOrdering, L.sszDecode(&buf, &out, std.testing.allocator));
}

test "utils.List.clone copies backing storage independently" {
const L = utils.List([]const u8, 4);
var data = try L.init(std.testing.allocator);
defer data.deinit();
try data.append("aa");
try data.append("bb");

var cloned = try data.clone(std.testing.allocator);
defer cloned.deinit();

try expect(cloned.len() == data.len());
try expect(cloned.inner.items.ptr != data.inner.items.ptr);
try expect(std.mem.eql(u8, (try cloned.get(0)), "aa"));
try expect((try cloned.get(0)).ptr == (try data.get(0)).ptr);
}

test "utils.List.clone with variable-sized struct items" {
const L = utils.List(Pastry, 8);
var data = try L.init(std.testing.allocator);
defer data.deinit();
try data.append(pastries[0]);
try data.append(pastries[1]);

var cloned = try data.clone(std.testing.allocator);
defer cloned.deinit();

try expect(cloned.len() == 2);
try expect(cloned.inner.items.ptr != data.inner.items.ptr);
try expect((try cloned.get(0)).weight == pastries[0].weight);
try expect((try cloned.get(1)).weight == pastries[1].weight);
// Item-level []const u8 fields stay borrowed (shallow item copy).
try expect((try cloned.get(0)).name.ptr == pastries[0].name.ptr);
try expect((try cloned.get(1)).name.ptr == pastries[1].name.ptr);
}

test "utils.Bitlist.clone copies backing storage independently" {
const B = utils.Bitlist(32);
var data = try B.init(std.testing.allocator);
defer data.deinit();
try data.append(true);
try data.append(false);
try data.append(true);

var cloned = try data.clone(std.testing.allocator);
defer cloned.deinit();

try expect(cloned.eql(&data));
try cloned.set(0, false);
try expect((try data.get(0)) == true);
}

test {
_ = @import("beacon_tests.zig");
}
17 changes: 17 additions & 0 deletions src/utils.zig
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,14 @@ pub fn List(T: type, comptime N: usize) type {
try serialize([]const Item, self.constSlice(), l, allocator);
}

/// Clones this list's backing storage; item ownership matches normal List values.
pub fn clone(self: *const Self, allocator: Allocator) !Self {
var cloned = try Self.init(allocator);
errdefer cloned.deinit();
try cloned.inner.appendSlice(allocator, self.inner.items);
return cloned;
}

pub fn isFixedSizeObject() bool {
return false;
}
Expand Down Expand Up @@ -254,6 +262,15 @@ pub fn Bitlist(comptime N: usize) type {
}
}

/// Clones this bitlist's backing storage.
pub fn clone(self: *const Self, allocator: Allocator) !Self {
var cloned = try Self.init(allocator);
errdefer cloned.deinit();
cloned.length = self.length;
try cloned.inner.appendSlice(allocator, self.inner.items);
return cloned;
}

pub fn sszDecode(serialized: []const u8, out: *Self, allocator: ?std.mem.Allocator) !void {
const alloc = allocator orelse return error.AllocatorRequired;
out.* = try init(alloc);
Expand Down
Loading