authorgravatar for motiejus@jakstys.ltMotiejus Jakštys <motiejus@jakstys.lt> 2023-03-17 18:50:25+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2023-03-17 17:50:25+01:00
loge0dd20b02ea026e125b36b3674f20aa20ff043e3
treee1536da7724b4822695028de04d02f9c296fb21b
parentcfcd6698cd9385938df27a2052c2309229171e4f
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

add BoundedArrayAligned (#14580)

This is useful for creating byte buffers of actually-different-things. Copied the argument order from `Allocator.alignedAlloc` I noted that `ArrayListAligned` is going out of it's way to not set the alignment at comptime when it is not specified. However, I was not able to do that the same way here, and good people on IRC, @ifreund in particular (thanks!) assured me that [N]T align(@alignOf(T)) is equivalent to [N]T

2 files changed, 40 insertions(+), 6 deletions(-)

lib/std/bounded_array.zig+39-6
...@@ -16,9 +16,30 @@ const testing = std.testing;...@@ -16,9 +16,30 @@ const testing = std.testing;
16/// var a_clone = a; // creates a copy - the structure doesn't use any internal pointers16/// var a_clone = a; // creates a copy - the structure doesn't use any internal pointers
17/// ```17/// ```
18pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {18pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
19 return BoundedArrayAligned(T, @alignOf(T), buffer_capacity);
20}
21
22/// A structure with an array, length and alignment, that can be used as a
23/// slice.
24///
25/// Useful to pass around small explicitly-aligned arrays whose exact size is
26/// only known at runtime, but whose maximum size is known at comptime, without
27/// requiring an `Allocator`.
28/// ```zig
29// var a = try BoundedArrayAligned(u8, 16, 2).init(0);
30// try a.append(255);
31// try a.append(255);
32// const b = @ptrCast(*const [1]u16, a.constSlice().ptr);
33// try testing.expectEqual(@as(u16, 65535), b[0]);
34/// ```
35pub fn BoundedArrayAligned(
36 comptime T: type,
37 comptime alignment: u29,
38 comptime buffer_capacity: usize,
39) type {
19 return struct {40 return struct {
20 const Self = @This();41 const Self = @This();
21 buffer: [buffer_capacity]T = undefined,42 buffer: [buffer_capacity]T align(alignment) = undefined,
22 len: usize = 0,43 len: usize = 0,
2344
24 /// Set the actual length of the slice.45 /// Set the actual length of the slice.
...@@ -30,15 +51,15 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {...@@ -30,15 +51,15 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
3051
31 /// View the internal array as a slice whose size was previously set.52 /// View the internal array as a slice whose size was previously set.
32 pub fn slice(self: anytype) switch (@TypeOf(&self.buffer)) {53 pub fn slice(self: anytype) switch (@TypeOf(&self.buffer)) {
33 *[buffer_capacity]T => []T,54 *align(alignment) [buffer_capacity]T => []align(alignment) T,
34 *const [buffer_capacity]T => []const T,55 *align(alignment) const [buffer_capacity]T => []align(alignment) const T,
35 else => unreachable,56 else => unreachable,
36 } {57 } {
37 return self.buffer[0..self.len];58 return self.buffer[0..self.len];
38 }59 }
3960
40 /// View the internal array as a constant slice whose size was previously set.61 /// View the internal array as a constant slice whose size was previously set.
41 pub fn constSlice(self: *const Self) []const T {62 pub fn constSlice(self: *const Self) []align(alignment) const T {
42 return self.slice();63 return self.slice();
43 }64 }
4465
...@@ -94,7 +115,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {...@@ -94,7 +115,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
94115
95 /// Resize the slice, adding `n` new elements, which have `undefined` values.116 /// Resize the slice, adding `n` new elements, which have `undefined` values.
96 /// The return value is a slice pointing to the uninitialized elements.117 /// The return value is a slice pointing to the uninitialized elements.
97 pub fn addManyAsArray(self: *Self, comptime n: usize) error{Overflow}!*[n]T {118 pub fn addManyAsArray(self: *Self, comptime n: usize) error{Overflow}!*align(alignment) [n]T {
98 const prev_len = self.len;119 const prev_len = self.len;
99 try self.resize(self.len + n);120 try self.resize(self.len + n);
100 return self.slice()[prev_len..][0..n];121 return self.slice()[prev_len..][0..n];
...@@ -118,7 +139,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {...@@ -118,7 +139,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type {
118 /// This can be useful for writing directly into it.139 /// This can be useful for writing directly into it.
119 /// Note that such an operation must be followed up with a140 /// Note that such an operation must be followed up with a
120 /// call to `resize()`141 /// call to `resize()`
121 pub fn unusedCapacitySlice(self: *Self) []T {142 pub fn unusedCapacitySlice(self: *Self) []align(alignment) T {
122 return self.buffer[self.len..];143 return self.buffer[self.len..];
123 }144 }
124145
...@@ -365,3 +386,15 @@ test "BoundedArray" {...@@ -365,3 +386,15 @@ test "BoundedArray" {
365 try w.writeAll(s);386 try w.writeAll(s);
366 try testing.expectEqualStrings(s, a.constSlice());387 try testing.expectEqualStrings(s, a.constSlice());
367}388}
389
390test "BoundedArrayAligned" {
391 var a = try BoundedArrayAligned(u8, 16, 4).init(0);
392 try a.append(0);
393 try a.append(0);
394 try a.append(255);
395 try a.append(255);
396
397 const b = @ptrCast(*const [2]u16, a.constSlice().ptr);
398 try testing.expectEqual(@as(u16, 0), b[0]);
399 try testing.expectEqual(@as(u16, 65535), b[1]);
400}
lib/std/std.zig+1
...@@ -9,6 +9,7 @@ pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;...@@ -9,6 +9,7 @@ pub const AutoArrayHashMapUnmanaged = array_hash_map.AutoArrayHashMapUnmanaged;
9pub const AutoHashMap = hash_map.AutoHashMap;9pub const AutoHashMap = hash_map.AutoHashMap;
10pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;10pub const AutoHashMapUnmanaged = hash_map.AutoHashMapUnmanaged;
11pub const BoundedArray = @import("bounded_array.zig").BoundedArray;11pub const BoundedArray = @import("bounded_array.zig").BoundedArray;
12pub const BoundedArrayAligned = @import("bounded_array.zig").BoundedArrayAligned;
12pub const Build = @import("Build.zig");13pub const Build = @import("Build.zig");
13pub const BufMap = @import("buf_map.zig").BufMap;14pub const BufMap = @import("buf_map.zig").BufMap;
14pub const BufSet = @import("buf_set.zig").BufSet;15pub const BufSet = @import("buf_set.zig").BufSet;