| ... | @@ -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 pointers | 16 | /// var a_clone = a; // creates a copy - the structure doesn't use any internal pointers |
| 17 | /// ``` | 17 | /// ``` |
| 18 | pub fn BoundedArray(comptime T: type, comptime buffer_capacity: usize) type { | 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 | 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, |
| 23 | | 44 | |
| 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 { |
| 30 | | 51 | |
| 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 | } |
| 39 | | 60 | |
| 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 | } |
| 44 | | 65 | |
| ... | @@ -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 { |
| 94 | | 115 | |
| 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 a | 140 | /// 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 | } |
| 124 | | 145 | |
| ... | @@ -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 | |
| | 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 | } |