| ... | @@ -16,7 +16,9 @@ const testing = std.testing; | ... | @@ -16,7 +16,9 @@ const testing = std.testing; |
| 16 | /// `.items(.<field_name>)` to obtain a slice of field values. | 16 | /// `.items(.<field_name>)` to obtain a slice of field values. |
| 17 | pub fn MultiArrayList(comptime S: type) type { | 17 | pub fn MultiArrayList(comptime S: type) type { |
| 18 | return struct { | 18 | return struct { |
| 19 | bytes: [*]align(@alignOf(S)) u8 = undefined, | 19 | const alignS = if (@alignOf(S) == 0) 1 else @alignOf(S); |
| | 20 | |
| | 21 | bytes: [*]align(alignS) u8 = undefined, |
| 20 | len: usize = 0, | 22 | len: usize = 0, |
| 21 | capacity: usize = 0, | 23 | capacity: usize = 0, |
| 22 | | 24 | |
| ... | @@ -50,8 +52,8 @@ pub fn MultiArrayList(comptime S: type) type { | ... | @@ -50,8 +52,8 @@ pub fn MultiArrayList(comptime S: type) type { |
| 50 | return .{}; | 52 | return .{}; |
| 51 | } | 53 | } |
| 52 | const unaligned_ptr = self.ptrs[sizes.fields[0]]; | 54 | const unaligned_ptr = self.ptrs[sizes.fields[0]]; |
| 53 | const aligned_ptr = @alignCast(@alignOf(S), unaligned_ptr); | 55 | const aligned_ptr = @alignCast(alignS, unaligned_ptr); |
| 54 | const casted_ptr = @ptrCast([*]align(@alignOf(S)) u8, aligned_ptr); | 56 | const casted_ptr = @ptrCast([*]align(alignS) u8, aligned_ptr); |
| 55 | return .{ | 57 | return .{ |
| 56 | .bytes = casted_ptr, | 58 | .bytes = casted_ptr, |
| 57 | .len = self.len, | 59 | .len = self.len, |
| ... | @@ -261,7 +263,7 @@ pub fn MultiArrayList(comptime S: type) type { | ... | @@ -261,7 +263,7 @@ pub fn MultiArrayList(comptime S: type) type { |
| 261 | | 263 | |
| 262 | const other_bytes = gpa.allocAdvanced( | 264 | const other_bytes = gpa.allocAdvanced( |
| 263 | u8, | 265 | u8, |
| 264 | @alignOf(S), | 266 | alignS, |
| 265 | capacityInBytes(new_len), | 267 | capacityInBytes(new_len), |
| 266 | .exact, | 268 | .exact, |
| 267 | ) catch { | 269 | ) catch { |
| ... | @@ -339,7 +341,7 @@ pub fn MultiArrayList(comptime S: type) type { | ... | @@ -339,7 +341,7 @@ pub fn MultiArrayList(comptime S: type) type { |
| 339 | assert(new_capacity >= self.len); | 341 | assert(new_capacity >= self.len); |
| 340 | const new_bytes = try gpa.allocAdvanced( | 342 | const new_bytes = try gpa.allocAdvanced( |
| 341 | u8, | 343 | u8, |
| 342 | @alignOf(S), | 344 | alignS, |
| 343 | capacityInBytes(new_capacity), | 345 | capacityInBytes(new_capacity), |
| 344 | .exact, | 346 | .exact, |
| 345 | ); | 347 | ); |
| ... | @@ -398,7 +400,7 @@ pub fn MultiArrayList(comptime S: type) type { | ... | @@ -398,7 +400,7 @@ pub fn MultiArrayList(comptime S: type) type { |
| 398 | return @reduce(.Add, capacity_vector * sizes_vector); | 400 | return @reduce(.Add, capacity_vector * sizes_vector); |
| 399 | } | 401 | } |
| 400 | | 402 | |
| 401 | fn allocatedBytes(self: Self) []align(@alignOf(S)) u8 { | 403 | fn allocatedBytes(self: Self) []align(alignS) u8 { |
| 402 | return self.bytes[0..capacityInBytes(self.capacity)]; | 404 | return self.bytes[0..capacityInBytes(self.capacity)]; |
| 403 | } | 405 | } |
| 404 | | 406 | |
| ... | @@ -621,3 +623,52 @@ test "insert elements" { | ... | @@ -621,3 +623,52 @@ test "insert elements" { |
| 621 | try testing.expectEqualSlices(u8, &[_]u8{ 1, 2 }, list.items(.a)); | 623 | try testing.expectEqualSlices(u8, &[_]u8{ 1, 2 }, list.items(.a)); |
| 622 | try testing.expectEqualSlices(u32, &[_]u32{ 2, 3 }, list.items(.b)); | 624 | try testing.expectEqualSlices(u32, &[_]u32{ 2, 3 }, list.items(.b)); |
| 623 | } | 625 | } |
| | 626 | |
| | 627 | test "0 sized struct field" { |
| | 628 | const ally = testing.allocator; |
| | 629 | |
| | 630 | const Foo = struct { |
| | 631 | a: u0, |
| | 632 | b: f32, |
| | 633 | }; |
| | 634 | |
| | 635 | var list = MultiArrayList(Foo){}; |
| | 636 | defer list.deinit(ally); |
| | 637 | |
| | 638 | try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); |
| | 639 | try testing.expectEqualSlices(f32, &[_]f32{}, list.items(.b)); |
| | 640 | |
| | 641 | try list.append(ally, .{ .a = 0, .b = 42.0 }); |
| | 642 | try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); |
| | 643 | try testing.expectEqualSlices(f32, &[_]f32{42.0}, list.items(.b)); |
| | 644 | |
| | 645 | try list.insert(ally, 0, .{ .a = 0, .b = -1.0 }); |
| | 646 | try testing.expectEqualSlices(u0, &[_]u0{ 0, 0 }, list.items(.a)); |
| | 647 | try testing.expectEqualSlices(f32, &[_]f32{ -1.0, 42.0 }, list.items(.b)); |
| | 648 | |
| | 649 | list.swapRemove(list.len - 1); |
| | 650 | try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); |
| | 651 | try testing.expectEqualSlices(f32, &[_]f32{-1.0}, list.items(.b)); |
| | 652 | } |
| | 653 | |
| | 654 | test "0 sized struct" { |
| | 655 | const ally = testing.allocator; |
| | 656 | |
| | 657 | const Foo = struct { |
| | 658 | a: u0, |
| | 659 | }; |
| | 660 | |
| | 661 | var list = MultiArrayList(Foo){}; |
| | 662 | defer list.deinit(ally); |
| | 663 | |
| | 664 | try testing.expectEqualSlices(u0, &[_]u0{}, list.items(.a)); |
| | 665 | |
| | 666 | try list.append(ally, .{ .a = 0 }); |
| | 667 | try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); |
| | 668 | |
| | 669 | try list.insert(ally, 0, .{ .a = 0 }); |
| | 670 | try testing.expectEqualSlices(u0, &[_]u0{ 0, 0 }, list.items(.a)); |
| | 671 | |
| | 672 | list.swapRemove(list.len - 1); |
| | 673 | try testing.expectEqualSlices(u0, &[_]u0{0}, list.items(.a)); |
| | 674 | } |