| ... | ... | @@ -4766,6 +4766,54 @@ test "sliceAsBytes preserves pointer attributes" { |
| 4766 | 4766 | try testing.expectEqual(in.alignment, out.alignment); |
| 4767 | 4767 | } |
| 4768 | 4768 | |
| 4769 | fn AbsorbSentinelReturnType(comptime Slice: type) type { |
| 4770 | const info = @typeInfo(Slice).pointer; |
| 4771 | assert(info.size == .slice); |
| 4772 | return @Pointer(.slice, .{ |
| 4773 | .@"const" = info.is_const, |
| 4774 | .@"volatile" = info.is_volatile, |
| 4775 | .@"allowzero" = info.is_allowzero, |
| 4776 | .@"addrspace" = info.address_space, |
| 4777 | .@"align" = info.alignment, |
| 4778 | }, info.child, null); |
| 4779 | } |
| 4780 | |
| 4781 | /// If the provided slice is not sentinel terminated, do nothing and return that slice. |
| 4782 | /// If it is sentinel-terminated, return a non-sentinel-terminated slice with the |
| 4783 | /// length increased by one to include the absorbed sentinel element. |
| 4784 | pub fn absorbSentinel(slice: anytype) AbsorbSentinelReturnType(@TypeOf(slice)) { |
| 4785 | const info = @typeInfo(@TypeOf(slice)).pointer; |
| 4786 | comptime assert(info.size == .slice); |
| 4787 | if (info.sentinel_ptr == null) { |
| 4788 | return slice; |
| 4789 | } else { |
| 4790 | return slice.ptr[0 .. slice.len + 1]; |
| 4791 | } |
| 4792 | } |
| 4793 | |
| 4794 | test absorbSentinel { |
| 4795 | { |
| 4796 | var buffer: [3:0]u8 = .{ 1, 2, 3 }; |
| 4797 | const foo: [:0]const u8 = &buffer; |
| 4798 | const bar: []const u8 = &buffer; |
| 4799 | try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo))); |
| 4800 | try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar))); |
| 4801 | try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo)); |
| 4802 | try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar)); |
| 4803 | } |
| 4804 | { |
| 4805 | var buffer: [3:0]u8 = .{ 1, 2, 3 }; |
| 4806 | const foo: [:0]u8 = &buffer; |
| 4807 | const bar: []u8 = &buffer; |
| 4808 | try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo))); |
| 4809 | try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar))); |
| 4810 | var expected_foo = [_]u8{ 1, 2, 3, 0 }; |
| 4811 | try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo)); |
| 4812 | var expected_bar = [_]u8{ 1, 2, 3 }; |
| 4813 | try testing.expectEqualSlices(u8, &expected_bar, absorbSentinel(bar)); |
| 4814 | } |
| 4815 | } |
| 4816 | |
| 4769 | 4817 | /// Round an address down to the next (or current) aligned address. |
| 4770 | 4818 | /// Unlike `alignForward`, `alignment` can be any positive number, not just a power of 2. |
| 4771 | 4819 | pub fn alignForwardAnyAlign(comptime T: type, addr: T, alignment: T) T { |