| ... | @@ -559,10 +559,14 @@ test "Span" { | ... | @@ -559,10 +559,14 @@ test "Span" { |
| 559 | /// When there is both a sentinel and an array length or slice length, the | 559 | /// When there is both a sentinel and an array length or slice length, the |
| 560 | /// length value is used instead of the sentinel. | 560 | /// length value is used instead of the sentinel. |
| 561 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { | 561 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| 562 | const Result = Span(@TypeOf(ptr)); | 562 | if (@typeInfo(@TypeOf(ptr)) == .Optional) { |
| 563 | if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) { | 563 | if (ptr) |non_null| { |
| 564 | return null; | 564 | return span(non_null); |
| | 565 | } else { |
| | 566 | return null; |
| | 567 | } |
| 565 | } | 568 | } |
| | 569 | const Result = Span(@TypeOf(ptr)); |
| 566 | const l = len(ptr); | 570 | const l = len(ptr); |
| 567 | if (@typeInfo(Result).Pointer.sentinel) |s| { | 571 | if (@typeInfo(Result).Pointer.sentinel) |s| { |
| 568 | return ptr[0..l :s]; | 572 | return ptr[0..l :s]; |
| ... | @@ -576,16 +580,21 @@ test "span" { | ... | @@ -576,16 +580,21 @@ test "span" { |
| 576 | const ptr = @as([*:3]u16, array[0..2 :3]); | 580 | const ptr = @as([*:3]u16, array[0..2 :3]); |
| 577 | testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); | 581 | testing.expect(eql(u16, span(ptr), &[_]u16{ 1, 2 })); |
| 578 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); | 582 | testing.expect(eql(u16, span(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| | 583 | testing.expectEqual(@as(?[:0]u16, null), span(@as(?[*:0]u16, null))); |
| 579 | } | 584 | } |
| 580 | | 585 | |
| 581 | /// Same as `span`, except when there is both a sentinel and an array | 586 | /// Same as `span`, except when there is both a sentinel and an array |
| 582 | /// length or slice length, scans the memory for the sentinel value | 587 | /// length or slice length, scans the memory for the sentinel value |
| 583 | /// rather than using the length. | 588 | /// rather than using the length. |
| 584 | pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) { | 589 | pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) { |
| 585 | const Result = Span(@TypeOf(ptr)); | 590 | if (@typeInfo(@TypeOf(ptr)) == .Optional) { |
| 586 | if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) { | 591 | if (ptr) |non_null| { |
| 587 | return null; | 592 | return spanZ(non_null); |
| | 593 | } else { |
| | 594 | return null; |
| | 595 | } |
| 588 | } | 596 | } |
| | 597 | const Result = Span(@TypeOf(ptr)); |
| 589 | const l = lenZ(ptr); | 598 | const l = lenZ(ptr); |
| 590 | if (@typeInfo(Result).Pointer.sentinel) |s| { | 599 | if (@typeInfo(Result).Pointer.sentinel) |s| { |
| 591 | return ptr[0..l :s]; | 600 | return ptr[0..l :s]; |
| ... | @@ -599,6 +608,7 @@ test "spanZ" { | ... | @@ -599,6 +608,7 @@ test "spanZ" { |
| 599 | const ptr = @as([*:3]u16, array[0..2 :3]); | 608 | const ptr = @as([*:3]u16, array[0..2 :3]); |
| 600 | testing.expect(eql(u16, spanZ(ptr), &[_]u16{ 1, 2 })); | 609 | testing.expect(eql(u16, spanZ(ptr), &[_]u16{ 1, 2 })); |
| 601 | testing.expect(eql(u16, spanZ(&array), &[_]u16{ 1, 2, 3, 4, 5 })); | 610 | testing.expect(eql(u16, spanZ(&array), &[_]u16{ 1, 2, 3, 4, 5 })); |
| | 611 | testing.expectEqual(@as(?[:0]u16, null), spanZ(@as(?[*:0]u16, null))); |
| 602 | } | 612 | } |
| 603 | | 613 | |
| 604 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, | 614 | /// Takes a pointer to an array, an array, a sentinel-terminated pointer, |