Compare commits

...

1 commit

Author SHA1 Message Date
Jay Petacat
fc74ffbe9d std.mem.sliceTo: Return slice with sentinel from unbounded pointers
Commit dec1163fbb removed sentinels from the returned slice for C
pointers. Since C pointers have no bounds, we know that it'll keep
scanning until it finds `end` (or crash trying). The same is also true
of many-item pointers without a sentinel (e.g. `[*]T`), so I added
support for those too.
2025-12-04 20:40:38 +01:00

View file

@ -913,8 +913,9 @@ fn SliceTo(comptime T: type, comptime end: std.meta.Elem(T)) type {
.pointer => |ptr_info| { .pointer => |ptr_info| {
const Elem = std.meta.Elem(T); const Elem = std.meta.Elem(T);
const have_sentinel: bool = switch (ptr_info.size) { const have_sentinel: bool = switch (ptr_info.size) {
.one, .slice, .many => if (std.meta.sentinel(T)) |s| s == end else false, .one, .slice => if (std.meta.sentinel(T)) |s| s == end else false,
.c => false, .many => if (std.meta.sentinel(T)) |s| s == end else true,
.c => true,
}; };
return @Pointer(.slice, .{ return @Pointer(.slice, .{
.@"const" = ptr_info.is_const, .@"const" = ptr_info.is_const,
@ -961,8 +962,15 @@ test sliceTo {
try testing.expectEqualSlices(u16, array[0..2], sliceTo(&array, 3)); try testing.expectEqualSlices(u16, array[0..2], sliceTo(&array, 3));
try testing.expectEqualSlices(u16, array[0..2], sliceTo(array[0..3], 3)); try testing.expectEqualSlices(u16, array[0..2], sliceTo(array[0..3], 3));
const many_ptr = @as([*]u16, @ptrCast(&array));
try testing.expectEqualSlices(u16, array[0..2], sliceTo(many_ptr, 3));
try testing.expectEqual([:3]u16, @TypeOf(sliceTo(many_ptr, 3)));
const sentinel_ptr = @as([*:5]u16, @ptrCast(&array)); const sentinel_ptr = @as([*:5]u16, @ptrCast(&array));
try testing.expectEqualSlices(u16, array[0..2], sliceTo(sentinel_ptr, 3)); try testing.expectEqualSlices(u16, array[0..2], sliceTo(sentinel_ptr, 3));
try testing.expectEqual([]u16, @TypeOf(sliceTo(sentinel_ptr, 3)));
try testing.expectEqualSlices(u16, array[0..4], sliceTo(sentinel_ptr, 5));
try testing.expectEqual([:5]u16, @TypeOf(sliceTo(sentinel_ptr, 5)));
try testing.expectEqualSlices(u16, array[0..4], sliceTo(sentinel_ptr, 99)); try testing.expectEqualSlices(u16, array[0..4], sliceTo(sentinel_ptr, 99));
const optional_sentinel_ptr = @as(?[*:5]u16, @ptrCast(&array)); const optional_sentinel_ptr = @as(?[*:5]u16, @ptrCast(&array));
@ -971,6 +979,7 @@ test sliceTo {
const c_ptr = @as([*c]u16, &array); const c_ptr = @as([*c]u16, &array);
try testing.expectEqualSlices(u16, array[0..2], sliceTo(c_ptr, 3)); try testing.expectEqualSlices(u16, array[0..2], sliceTo(c_ptr, 3));
try testing.expectEqual([:3]u16, @TypeOf(sliceTo(c_ptr, 3)));
const slice: []u16 = &array; const slice: []u16 = &array;
try testing.expectEqualSlices(u16, array[0..2], sliceTo(slice, 3)); try testing.expectEqualSlices(u16, array[0..2], sliceTo(slice, 3));
@ -1015,6 +1024,10 @@ fn lenSliceTo(ptr: anytype, comptime end: std.meta.Elem(@TypeOf(ptr))) usize {
var i: usize = 0; var i: usize = 0;
while (ptr[i] != end and ptr[i] != s) i += 1; while (ptr[i] != end and ptr[i] != s) i += 1;
return i; return i;
} else {
var i: usize = 0;
while (ptr[i] != end) i += 1;
return i;
}, },
.c => { .c => {
assert(ptr != null); assert(ptr != null);