| ... | ... | @@ -16,9 +16,30 @@ const testing = std.testing; |
| 16 | 16 | /// var a_clone = a; // creates a copy - the structure doesn't use any internal pointers |
| 17 | 17 | /// ``` |
| 18 | 18 | pub 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 | /// ``` |
| 35 | pub fn BoundedArrayAligned( |
| 36 | comptime T: type, |
| 37 | comptime alignment: u29, |
| 38 | comptime buffer_capacity: usize, |
| 39 | ) type { |
| 19 | 40 | return struct { |
| 20 | 41 | const Self = @This(); |
| 21 | | buffer: [buffer_capacity]T = undefined, |
| 42 | buffer: [buffer_capacity]T align(alignment) = undefined, |
| 22 | 43 | len: usize = 0, |
| 23 | 44 | |
| 24 | 45 | /// Set the actual length of the slice. |
| ... | ... | @@ -30,15 +51,15 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type { |
| 30 | 51 | |
| 31 | 52 | /// View the internal array as a slice whose size was previously set. |
| 32 | 53 | pub fn slice(self: anytype) switch (@TypeOf(&self.buffer)) { |
| 33 | | *[buffer_capacity]T => []T, |
| 34 | | *const [buffer_capacity]T => []const T, |
| 54 | *align(alignment) [buffer_capacity]T => []align(alignment) T, |
| 55 | *align(alignment) const [buffer_capacity]T => []align(alignment) const T, |
| 35 | 56 | else => unreachable, |
| 36 | 57 | } { |
| 37 | 58 | return self.buffer[0..self.len]; |
| 38 | 59 | } |
| 39 | 60 | |
| 40 | 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 | 63 | return self.slice(); |
| 43 | 64 | } |
| 44 | 65 | |
| ... | ... | @@ -94,7 +115,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type { |
| 94 | 115 | |
| 95 | 116 | /// Resize the slice, adding `n` new elements, which have `undefined` values. |
| 96 | 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 | 119 | const prev_len = self.len; |
| 99 | 120 | try self.resize(self.len + n); |
| 100 | 121 | return self.slice()[prev_len..][0..n]; |
| ... | ... | @@ -118,7 +139,7 @@ pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type { |
| 118 | 139 | /// This can be useful for writing directly into it. |
| 119 | 140 | /// Note that such an operation must be followed up with a |
| 120 | 141 | /// call to `resize()` |
| 121 | | pub fn unusedCapacitySlice(self: *Self) []T { |
| 142 | pub fn unusedCapacitySlice(self: *Self) []align(alignment) T { |
| 122 | 143 | return self.buffer[self.len..]; |
| 123 | 144 | } |
| 124 | 145 | |
| ... | ... | @@ -365,3 +386,15 @@ test "BoundedArray" { |
| 365 | 386 | try w.writeAll(s); |
| 366 | 387 | try testing.expectEqualStrings(s, a.constSlice()); |
| 367 | 388 | } |
| 389 | |
| 390 | test "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 | } |