| ... | @@ -512,36 +512,54 @@ pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { | ... | @@ -512,36 +512,54 @@ pub fn toSlice(comptime T: type, ptr: [*:0]T) [:0]T { |
| 512 | /// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated, | 512 | /// the constness of the input type. `[*c]` pointers are assumed to be 0-terminated, |
| 513 | /// and assumed to not allow null. | 513 | /// and assumed to not allow null. |
| 514 | pub fn Span(comptime T: type) type { | 514 | pub fn Span(comptime T: type) type { |
| 515 | var ptr_info = @typeInfo(T).Pointer; | 515 | switch(@typeInfo(T)) { |
| 516 | switch (ptr_info.size) { | 516 | .Optional => |optional_info| { |
| 517 | .One => switch (@typeInfo(ptr_info.child)) { | 517 | return ?Span(optional_info.child); |
| 518 | .Array => |info| { | | |
| 519 | ptr_info.child = info.child; | | |
| 520 | ptr_info.sentinel = info.sentinel; | | |
| 521 | }, | | |
| 522 | else => @compileError("invalid type given to std.mem.Span"), | | |
| 523 | }, | 518 | }, |
| 524 | .C => { | 519 | .Pointer => |ptr_info| { |
| 525 | ptr_info.sentinel = 0; | 520 | var new_ptr_info = ptr_info; |
| 526 | ptr_info.is_allowzero = false; | 521 | switch (ptr_info.size) { |
| | 522 | .One => switch (@typeInfo(ptr_info.child)) { |
| | 523 | .Array => |info| { |
| | 524 | new_ptr_info.child = info.child; |
| | 525 | new_ptr_info.sentinel = info.sentinel; |
| | 526 | }, |
| | 527 | else => @compileError("invalid type given to std.mem.Span"), |
| | 528 | }, |
| | 529 | .C => { |
| | 530 | new_ptr_info.sentinel = 0; |
| | 531 | new_ptr_info.is_allowzero = false; |
| | 532 | }, |
| | 533 | .Many, .Slice => {}, |
| | 534 | } |
| | 535 | new_ptr_info.size = .Slice; |
| | 536 | return @Type(std.builtin.TypeInfo{ .Pointer = new_ptr_info }); |
| 527 | }, | 537 | }, |
| 528 | .Many, .Slice => {}, | 538 | else => @compileError("invalid type given to std.mem.Span"), |
| 529 | } | 539 | } |
| 530 | ptr_info.size = .Slice; | | |
| 531 | return @Type(std.builtin.TypeInfo{ .Pointer = ptr_info }); | | |
| 532 | } | 540 | } |
| 533 | | 541 | |
| 534 | test "Span" { | 542 | test "Span" { |
| 535 | testing.expect(Span(*[5]u16) == []u16); | 543 | testing.expect(Span(*[5]u16) == []u16); |
| | 544 | testing.expect(Span(?*[5]u16) == ?[]u16); |
| 536 | testing.expect(Span(*const [5]u16) == []const u16); | 545 | testing.expect(Span(*const [5]u16) == []const u16); |
| | 546 | testing.expect(Span(?*const [5]u16) == ?[]const u16); |
| 537 | testing.expect(Span([]u16) == []u16); | 547 | testing.expect(Span([]u16) == []u16); |
| | 548 | testing.expect(Span(?[]u16) == ?[]u16); |
| 538 | testing.expect(Span([]const u8) == []const u8); | 549 | testing.expect(Span([]const u8) == []const u8); |
| | 550 | testing.expect(Span(?[]const u8) == ?[]const u8); |
| 539 | testing.expect(Span([:1]u16) == [:1]u16); | 551 | testing.expect(Span([:1]u16) == [:1]u16); |
| | 552 | testing.expect(Span(?[:1]u16) == ?[:1]u16); |
| 540 | testing.expect(Span([:1]const u8) == [:1]const u8); | 553 | testing.expect(Span([:1]const u8) == [:1]const u8); |
| | 554 | testing.expect(Span(?[:1]const u8) == ?[:1]const u8); |
| 541 | testing.expect(Span([*:1]u16) == [:1]u16); | 555 | testing.expect(Span([*:1]u16) == [:1]u16); |
| | 556 | testing.expect(Span(?[*:1]u16) == ?[:1]u16); |
| 542 | testing.expect(Span([*:1]const u8) == [:1]const u8); | 557 | testing.expect(Span([*:1]const u8) == [:1]const u8); |
| | 558 | testing.expect(Span(?[*:1]const u8) == ?[:1]const u8); |
| 543 | testing.expect(Span([*c]u16) == [:0]u16); | 559 | testing.expect(Span([*c]u16) == [:0]u16); |
| | 560 | testing.expect(Span(?[*c]u16) == ?[:0]u16); |
| 544 | testing.expect(Span([*c]const u8) == [:0]const u8); | 561 | testing.expect(Span([*c]const u8) == [:0]const u8); |
| | 562 | testing.expect(Span(?[*c]const u8) == ?[:0]const u8); |
| 545 | } | 563 | } |
| 546 | | 564 | |
| 547 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and | 565 | /// Takes a pointer to an array, a sentinel-terminated pointer, or a slice, and |
| ... | @@ -553,6 +571,9 @@ test "Span" { | ... | @@ -553,6 +571,9 @@ test "Span" { |
| 553 | /// length value is used instead of the sentinel. | 571 | /// length value is used instead of the sentinel. |
| 554 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { | 572 | pub fn span(ptr: var) Span(@TypeOf(ptr)) { |
| 555 | const Result = Span(@TypeOf(ptr)); | 573 | const Result = Span(@TypeOf(ptr)); |
| | 574 | if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) { |
| | 575 | return null; |
| | 576 | } |
| 556 | const l = len(ptr); | 577 | const l = len(ptr); |
| 557 | if (@typeInfo(Result).Pointer.sentinel) |s| { | 578 | if (@typeInfo(Result).Pointer.sentinel) |s| { |
| 558 | return ptr[0..l :s]; | 579 | return ptr[0..l :s]; |
| ... | @@ -573,6 +594,9 @@ test "span" { | ... | @@ -573,6 +594,9 @@ test "span" { |
| 573 | /// rather than using the length. | 594 | /// rather than using the length. |
| 574 | pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) { | 595 | pub fn spanZ(ptr: var) Span(@TypeOf(ptr)) { |
| 575 | const Result = Span(@TypeOf(ptr)); | 596 | const Result = Span(@TypeOf(ptr)); |
| | 597 | if (@typeInfo(@TypeOf(ptr)) == .Optional and ptr == null) { |
| | 598 | return null; |
| | 599 | } |
| 576 | const l = lenZ(ptr); | 600 | const l = lenZ(ptr); |
| 577 | if (@typeInfo(Result).Pointer.sentinel) |s| { | 601 | if (@typeInfo(Result).Pointer.sentinel) |s| { |
| 578 | return ptr[0..l :s]; | 602 | return ptr[0..l :s]; |