@@ -333,8 +333,20 @@ pub fn zeroes(comptime T: type) T {
333
333
}
334
334
return array ;
335
335
},
336
- .Vector , .ErrorUnion , .ErrorSet , .Union , .Fn , .BoundFn , .Type , .NoReturn , .Undefined , .Opaque , .Frame , .AnyFrame , = > {
337
- @compileError ("Can't set a " ++ @typeName (T ) ++ " to zero." );
336
+ .Vector ,
337
+ .ErrorUnion ,
338
+ .ErrorSet ,
339
+ .Union ,
340
+ .Fn ,
341
+ .BoundFn ,
342
+ .Type ,
343
+ .NoReturn ,
344
+ .Undefined ,
345
+ .Opaque ,
346
+ .Frame ,
347
+ .AnyFrame ,
348
+ = > {
349
+ @compileError ("Can't set a " ++ @typeName (T ) ++ " to zero." );
338
350
},
339
351
}
340
352
}
@@ -470,20 +482,122 @@ pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
470
482
return true ;
471
483
}
472
484
485
+ /// Deprecated. Use `length` or `indexOfSentinel`.
473
486
pub fn len (comptime T : type , ptr : [* :0 ]const T ) usize {
474
487
var count : usize = 0 ;
475
488
while (ptr [count ] != 0 ) : (count += 1 ) {}
476
489
return count ;
477
490
}
478
491
492
+ /// Deprecated. Use `span`.
479
493
pub fn toSliceConst (comptime T : type , ptr : [* :0 ]const T ) [:0 ]const T {
480
494
return ptr [0.. len (T , ptr ) :0 ];
481
495
}
482
496
497
+ /// Deprecated. Use `span`.
483
498
pub fn toSlice (comptime T : type , ptr : [* :0 ]T ) [:0 ]T {
484
499
return ptr [0.. len (T , ptr ) :0 ];
485
500
}
486
501
502
+ /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
503
+ /// returns a slice. If there is a sentinel on the input type, there will be a
504
+ /// sentinel on the output type. The constness of the output type matches
505
+ /// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated.
506
+ pub fn Span (comptime T : type ) type {
507
+ var ptr_info = @typeInfo (T ).Pointer ;
508
+ switch (ptr_info .size ) {
509
+ .One = > switch (@typeInfo (ptr_info .child )) {
510
+ .Array = > | info | {
511
+ ptr_info .child = info .child ;
512
+ ptr_info .sentinel = info .sentinel ;
513
+ },
514
+ else = > @compileError ("invalid type given to std.mem.Span" ),
515
+ },
516
+ .C = > {
517
+ ptr_info .sentinel = 0 ;
518
+ },
519
+ .Many , .Slice = > {},
520
+ }
521
+ ptr_info .size = .Slice ;
522
+ return @Type (std.builtin.TypeInfo { .Pointer = ptr_info });
523
+ }
524
+
525
+ test "Span" {
526
+ testing .expect (Span (* [5 ]u16 ) == []u16 );
527
+ testing .expect (Span (* const [5 ]u16 ) == []const u16 );
528
+ testing .expect (Span ([]u16 ) == []u16 );
529
+ testing .expect (Span ([]const u8 ) == []const u8 );
530
+ testing .expect (Span ([:1 ]u16 ) == [:1 ]u16 );
531
+ testing .expect (Span ([:1 ]const u8 ) == [:1 ]const u8 );
532
+ testing .expect (Span ([* :1 ]u16 ) == [:1 ]u16 );
533
+ testing .expect (Span ([* :1 ]const u8 ) == [:1 ]const u8 );
534
+ testing .expect (Span ([* c ]u16 ) == [:0 ]u16 );
535
+ testing .expect (Span ([* c ]const u8 ) == [:0 ]const u8 );
536
+ }
537
+
538
+ /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and
539
+ /// returns a slice. If there is a sentinel on the input type, there will be a
540
+ /// sentinel on the output type. The constness of the output type matches
541
+ /// the constness of the input type.
542
+ pub fn span (ptr : var ) Span (@TypeOf (ptr )) {
543
+ const Result = Span (@TypeOf (ptr ));
544
+ const l = length (ptr );
545
+ if (@typeInfo (Result ).Pointer .sentinel ) | s | {
546
+ return ptr [0.. l :s ];
547
+ } else {
548
+ return ptr [0.. l ];
549
+ }
550
+ }
551
+
552
+ test "span" {
553
+ var array : [5 ]u16 = [_ ]u16 { 1 , 2 , 3 , 4 , 5 };
554
+ const ptr = array [0.. 2 :3 ].ptr ;
555
+ testing .expect (eql (u16 , span (ptr ), &[_ ]u16 { 1 , 2 }));
556
+ testing .expect (eql (u16 , span (& array ), &[_ ]u16 { 1 , 2 , 3 , 4 , 5 }));
557
+ }
558
+
559
+ /// Takes a pointer to an array, an array, a sentinel-terminated pointer,
560
+ /// or a slice, and returns the length.
561
+ pub fn length (ptr : var ) usize {
562
+ return switch (@typeInfo (@TypeOf (ptr ))) {
563
+ .Array = > | info | info .len ,
564
+ .Pointer = > | info | switch (info .size ) {
565
+ .One = > switch (@typeInfo (info .child )) {
566
+ .Array = > | x | x .len ,
567
+ else = > @compileError ("invalid type given to std.mem.length" ),
568
+ },
569
+ .Many = > if (info .sentinel ) | sentinel |
570
+ indexOfSentinel (info .child , sentinel , ptr )
571
+ else
572
+ @compileError ("length of pointer with no sentinel" ),
573
+ .C = > indexOfSentinel (info .child , 0 , ptr ),
574
+ .Slice = > ptr .len ,
575
+ },
576
+ else = > @compileError ("invalid type given to std.mem.length" ),
577
+ };
578
+ }
579
+
580
+ test "length" {
581
+ testing .expect (length ("aoeu" ) == 4 );
582
+
583
+ {
584
+ var array : [5 ]u16 = [_ ]u16 { 1 , 2 , 3 , 4 , 5 };
585
+ testing .expect (length (& array ) == 5 );
586
+ testing .expect (length (array [0.. 3]) == 3 );
587
+ array [2 ] = 0 ;
588
+ const ptr = array [0.. 2 :0 ].ptr ;
589
+ testing .expect (length (ptr ) == 2 );
590
+ }
591
+ }
592
+
593
+ pub fn indexOfSentinel (comptime Elem : type , comptime sentinel : Elem , ptr : [* :sentinel ]const Elem ) usize {
594
+ var i : usize = 0 ;
595
+ while (ptr [i ] != sentinel ) {
596
+ i += 1 ;
597
+ }
598
+ return i ;
599
+ }
600
+
487
601
/// Returns true if all elements in a slice are equal to the scalar value provided
488
602
pub fn allEqual (comptime T : type , slice : []const T , scalar : T ) bool {
489
603
for (slice ) | item | {
0 commit comments