From d2a0a2db28468aa6208e60fc752bc58a61a64cff Mon Sep 17 00:00:00 2001 From: John Simon Date: Sun, 2 Jul 2023 09:21:06 -0400 Subject: [PATCH 1/4] Add sizeOf test --- lib/std/bounded_array.zig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/lib/std/bounded_array.zig b/lib/std/bounded_array.zig index 6986414a24e9..9b633c3b3d90 100644 --- a/lib/std/bounded_array.zig +++ b/lib/std/bounded_array.zig @@ -387,6 +387,13 @@ test "BoundedArray" { try testing.expectEqualStrings(s, a.constSlice()); } +test "BoundedArray sizeOf" { + // Just sanity check size on one CPU + if (@import("builtin").cpu.arch != .x86_64) + return; + try testing.expectEqual(@sizeOf(BoundedArray(u8, 3)), 16); +} + test "BoundedArrayAligned" { var a = try BoundedArrayAligned(u8, 16, 4).init(0); try a.append(0); From 92e10d3190e5bdf70b18b53257a6269f41e1e005 Mon Sep 17 00:00:00 2001 From: John Simon Date: Sun, 2 Jul 2023 10:04:56 -0400 Subject: [PATCH 2/4] Store BoundedArray's length using the smallest possible integer --- lib/std/bounded_array.zig | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/lib/std/bounded_array.zig b/lib/std/bounded_array.zig index 9b633c3b3d90..c037a0c196da 100644 --- a/lib/std/bounded_array.zig +++ b/lib/std/bounded_array.zig @@ -39,14 +39,17 @@ pub fn BoundedArrayAligned( ) type { return struct { const Self = @This(); + /// Smallest integer type that is able to hold values from 0 to `buffer_capacity`. + const Len = std.meta.Int(.unsigned, std.math.log2_int(u16, buffer_capacity) + 1); + buffer: [buffer_capacity]T align(alignment) = undefined, - len: usize = 0, + len: Len = 0, /// Set the actual length of the slice. /// Returns error.Overflow if it exceeds the length of the backing array. pub fn init(len: usize) error{Overflow}!Self { if (len > buffer_capacity) return error.Overflow; - return Self{ .len = len }; + return Self{ .len = @intCast(len) }; } /// View the internal array as a slice whose size was previously set. @@ -67,7 +70,7 @@ pub fn BoundedArrayAligned( /// Does not initialize added items if any. pub fn resize(self: *Self, len: usize) error{Overflow}!void { if (len > buffer_capacity) return error.Overflow; - self.len = len; + self.len = @intCast(len); } /// Copy the content of an existing slice. @@ -163,7 +166,7 @@ pub fn BoundedArrayAligned( /// This operation is O(N). pub fn insertSlice(self: *Self, i: usize, items: []const T) error{Overflow}!void { try self.ensureUnusedCapacity(items.len); - self.len += items.len; + self.len += @intCast(items.len); mem.copyBackwards(T, self.slice()[i + items.len .. self.len], self.constSlice()[i .. self.len - items.len]); @memcpy(self.slice()[i..][0..items.len], items); } @@ -193,7 +196,7 @@ pub fn BoundedArrayAligned( for (self.constSlice()[after_range..], 0..) |item, i| { self.slice()[after_subrange..][i] = item; } - self.len -= len - new_items.len; + self.len -= @intCast(len - new_items.len); } } @@ -244,7 +247,7 @@ pub fn BoundedArrayAligned( /// enough to store the new items. pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { const old_len = self.len; - self.len += items.len; + self.len += @intCast(items.len); @memcpy(self.slice()[old_len..][0..items.len], items); } @@ -260,8 +263,8 @@ pub fn BoundedArrayAligned( /// Asserts the capacity is enough. pub fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { const old_len = self.len; - self.len += n; - assert(self.len <= buffer_capacity); + assert(self.len + n <= buffer_capacity); + self.len += @intCast(n); @memset(self.slice()[old_len..self.len], value); } @@ -391,7 +394,12 @@ test "BoundedArray sizeOf" { // Just sanity check size on one CPU if (@import("builtin").cpu.arch != .x86_64) return; - try testing.expectEqual(@sizeOf(BoundedArray(u8, 3)), 16); + + try testing.expectEqual(@sizeOf(BoundedArray(u8, 3)), 4); + + // `len` is the minimum required size to hold the maximum capacity + try testing.expectEqual(@TypeOf(@as(BoundedArray(u8, 15), undefined).len), u4); + try testing.expectEqual(@TypeOf(@as(BoundedArray(u8, 16), undefined).len), u5); } test "BoundedArrayAligned" { From a1a27fa4e299aceb47e126ebc28f6d4a7e3d1984 Mon Sep 17 00:00:00 2001 From: John Simon Date: Sun, 2 Jul 2023 17:10:13 +0000 Subject: [PATCH 3/4] Calculate Len in a clearer way Co-authored-by: zooster --- lib/std/bounded_array.zig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/std/bounded_array.zig b/lib/std/bounded_array.zig index c037a0c196da..a09950fa52f6 100644 --- a/lib/std/bounded_array.zig +++ b/lib/std/bounded_array.zig @@ -39,8 +39,7 @@ pub fn BoundedArrayAligned( ) type { return struct { const Self = @This(); - /// Smallest integer type that is able to hold values from 0 to `buffer_capacity`. - const Len = std.meta.Int(.unsigned, std.math.log2_int(u16, buffer_capacity) + 1); + const Len = std.math.IntFittingRange(0, buffer_capacity); buffer: [buffer_capacity]T align(alignment) = undefined, len: Len = 0, From 13bdda4d638ccefac29b8f15d11b0e66177aea04 Mon Sep 17 00:00:00 2001 From: John Simon Date: Mon, 3 Jul 2023 09:11:07 -0400 Subject: [PATCH 4/4] Cast after doing math so the generated code is more efficient --- lib/std/bounded_array.zig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/bounded_array.zig b/lib/std/bounded_array.zig index a09950fa52f6..9867754dcd0a 100644 --- a/lib/std/bounded_array.zig +++ b/lib/std/bounded_array.zig @@ -165,7 +165,7 @@ pub fn BoundedArrayAligned( /// This operation is O(N). pub fn insertSlice(self: *Self, i: usize, items: []const T) error{Overflow}!void { try self.ensureUnusedCapacity(items.len); - self.len += @intCast(items.len); + self.len = @intCast(self.len + items.len); mem.copyBackwards(T, self.slice()[i + items.len .. self.len], self.constSlice()[i .. self.len - items.len]); @memcpy(self.slice()[i..][0..items.len], items); } @@ -195,7 +195,7 @@ pub fn BoundedArrayAligned( for (self.constSlice()[after_range..], 0..) |item, i| { self.slice()[after_subrange..][i] = item; } - self.len -= @intCast(len - new_items.len); + self.len = @intCast(self.len - len + new_items.len); } } @@ -246,7 +246,7 @@ pub fn BoundedArrayAligned( /// enough to store the new items. pub fn appendSliceAssumeCapacity(self: *Self, items: []const T) void { const old_len = self.len; - self.len += @intCast(items.len); + self.len = @intCast(self.len + items.len); @memcpy(self.slice()[old_len..][0..items.len], items); } @@ -263,7 +263,7 @@ pub fn BoundedArrayAligned( pub fn appendNTimesAssumeCapacity(self: *Self, value: T, n: usize) void { const old_len = self.len; assert(self.len + n <= buffer_capacity); - self.len += @intCast(n); + self.len = @intCast(self.len + n); @memset(self.slice()[old_len..self.len], value); }