@@ -4413,6 +4413,59 @@ test "sliceAsBytes preserves pointer attributes" {
4413
4413
try testing .expectEqual (in .alignment , out .alignment );
4414
4414
}
4415
4415
4416
+ fn AbsorbSentinelReturnType (comptime Slice : type ) type {
4417
+ const info = @typeInfo (Slice ).pointer ;
4418
+ assert (info .size == .slice );
4419
+ return @Type (.{
4420
+ .pointer = .{
4421
+ .size = info .size ,
4422
+ .is_const = info .is_const ,
4423
+ .is_volatile = info .is_volatile ,
4424
+ .is_allowzero = info .is_allowzero ,
4425
+ .alignment = info .alignment ,
4426
+ .address_space = info .address_space ,
4427
+ .child = info .child ,
4428
+ .sentinel_ptr = null ,
4429
+ },
4430
+ });
4431
+ }
4432
+
4433
+ /// If the provided slice is not sentinel terminated, do nothing and return that slice.
4434
+ /// If it is sentinel-terminated, return a non-sentinel-terminated slice with the
4435
+ /// length increased by one to include the absorbed sentinel element.
4436
+ pub fn absorbSentinel (slice : anytype ) AbsorbSentinelReturnType (@TypeOf (slice )) {
4437
+ const info = @typeInfo (@TypeOf (slice )).pointer ;
4438
+ assert (info .size == .slice );
4439
+ if (info .sentinel_ptr == null ) {
4440
+ return slice ;
4441
+ } else {
4442
+ return slice .ptr [0 .. slice .len + 1 ];
4443
+ }
4444
+ }
4445
+
4446
+ test absorbSentinel {
4447
+ {
4448
+ var buffer : [3 :0 ]u8 = .{ 1 , 2 , 3 };
4449
+ const foo : [:0 ]const u8 = & buffer ;
4450
+ const bar : []const u8 = & buffer ;
4451
+ try testing .expectEqual ([]const u8 , @TypeOf (absorbSentinel (foo )));
4452
+ try testing .expectEqual ([]const u8 , @TypeOf (absorbSentinel (bar )));
4453
+ try testing .expectEqualSlices (u8 , &.{ 1 , 2 , 3 , 0 }, absorbSentinel (foo ));
4454
+ try testing .expectEqualSlices (u8 , &.{ 1 , 2 , 3 }, absorbSentinel (bar ));
4455
+ }
4456
+ {
4457
+ var buffer : [3 :0 ]u8 = .{ 1 , 2 , 3 };
4458
+ const foo : [:0 ]u8 = & buffer ;
4459
+ const bar : []u8 = & buffer ;
4460
+ try testing .expectEqual ([]u8 , @TypeOf (absorbSentinel (foo )));
4461
+ try testing .expectEqual ([]u8 , @TypeOf (absorbSentinel (bar )));
4462
+ var expected_foo = [_ ]u8 { 1 , 2 , 3 , 0 };
4463
+ try testing .expectEqualSlices (u8 , & expected_foo , absorbSentinel (foo ));
4464
+ var expected_bar = [_ ]u8 { 1 , 2 , 3 };
4465
+ try testing .expectEqualSlices (u8 , & expected_bar , absorbSentinel (bar ));
4466
+ }
4467
+ }
4468
+
4416
4469
/// Round an address down to the next (or current) aligned address.
4417
4470
/// Unlike `alignForward`, `alignment` can be any positive number, not just a power of 2.
4418
4471
pub fn alignForwardAnyAlign (comptime T : type , addr : T , alignment : T ) T {
0 commit comments