mirror of
https://codeberg.org/ziglang/zig.git
synced 2026-04-27 19:09:47 +03:00
std: add mem.absorbSentinel()
This will allow replacing (currently buggy) mem.sliceAsBytes() usage in the mem.Allocator implementation with, for example: const bytes: []u8 = @constCast(@ptrCast(mem.absorbSentinel(allocation))); References: https://github.com/ziglang/zig/pull/22706
This commit is contained in:
@@ -4766,6 +4766,54 @@ test "sliceAsBytes preserves pointer attributes" {
|
||||
try testing.expectEqual(in.alignment, out.alignment);
|
||||
}
|
||||
|
||||
fn AbsorbSentinelReturnType(comptime Slice: type) type {
|
||||
const info = @typeInfo(Slice).pointer;
|
||||
assert(info.size == .slice);
|
||||
return @Pointer(.slice, .{
|
||||
.@"const" = info.is_const,
|
||||
.@"volatile" = info.is_volatile,
|
||||
.@"allowzero" = info.is_allowzero,
|
||||
.@"addrspace" = info.address_space,
|
||||
.@"align" = info.alignment,
|
||||
}, info.child, null);
|
||||
}
|
||||
|
||||
/// If the provided slice is not sentinel terminated, do nothing and return that slice.
|
||||
/// If it is sentinel-terminated, return a non-sentinel-terminated slice with the
|
||||
/// length increased by one to include the absorbed sentinel element.
|
||||
pub fn absorbSentinel(slice: anytype) AbsorbSentinelReturnType(@TypeOf(slice)) {
|
||||
const info = @typeInfo(@TypeOf(slice)).pointer;
|
||||
comptime assert(info.size == .slice);
|
||||
if (info.sentinel_ptr == null) {
|
||||
return slice;
|
||||
} else {
|
||||
return slice.ptr[0 .. slice.len + 1];
|
||||
}
|
||||
}
|
||||
|
||||
test absorbSentinel {
|
||||
{
|
||||
var buffer: [3:0]u8 = .{ 1, 2, 3 };
|
||||
const foo: [:0]const u8 = &buffer;
|
||||
const bar: []const u8 = &buffer;
|
||||
try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(foo)));
|
||||
try testing.expectEqual([]const u8, @TypeOf(absorbSentinel(bar)));
|
||||
try testing.expectEqualSlices(u8, &.{ 1, 2, 3, 0 }, absorbSentinel(foo));
|
||||
try testing.expectEqualSlices(u8, &.{ 1, 2, 3 }, absorbSentinel(bar));
|
||||
}
|
||||
{
|
||||
var buffer: [3:0]u8 = .{ 1, 2, 3 };
|
||||
const foo: [:0]u8 = &buffer;
|
||||
const bar: []u8 = &buffer;
|
||||
try testing.expectEqual([]u8, @TypeOf(absorbSentinel(foo)));
|
||||
try testing.expectEqual([]u8, @TypeOf(absorbSentinel(bar)));
|
||||
var expected_foo = [_]u8{ 1, 2, 3, 0 };
|
||||
try testing.expectEqualSlices(u8, &expected_foo, absorbSentinel(foo));
|
||||
var expected_bar = [_]u8{ 1, 2, 3 };
|
||||
try testing.expectEqualSlices(u8, &expected_bar, absorbSentinel(bar));
|
||||
}
|
||||
}
|
||||
|
||||
/// Round an address down to the next (or current) aligned address.
|
||||
/// Unlike `alignForward`, `alignment` can be any positive number, not just a power of 2.
|
||||
pub fn alignForwardAnyAlign(comptime T: type, addr: T, alignment: T) T {
|
||||
|
||||
Reference in New Issue
Block a user