| ... | @@ -593,48 +593,29 @@ pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void { | ... | @@ -593,48 +593,29 @@ pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void { |
| 593 | /// See also: | 593 | /// See also: |
| 594 | /// * `readSliceAll` | 594 | /// * `readSliceAll` |
| 595 | pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize { | 595 | pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize { |
| 596 | const in_buffer = r.buffer[r.seek..r.end]; | 596 | var i: usize = 0; |
| 597 | const copy_len = @min(buffer.len, in_buffer.len); | | |
| 598 | @memcpy(buffer[0..copy_len], in_buffer[0..copy_len]); | | |
| 599 | if (buffer.len - copy_len == 0) { | | |
| 600 | r.seek += copy_len; | | |
| 601 | return buffer.len; | | |
| 602 | } | | |
| 603 | var i: usize = copy_len; | | |
| 604 | r.end = 0; | | |
| 605 | r.seek = 0; | | |
| 606 | while (true) { | 597 | while (true) { |
| | 598 | const buffer_contents = r.buffer[r.seek..r.end]; |
| | 599 | const dest = buffer[i..]; |
| | 600 | const copy_len = @min(dest.len, buffer_contents.len); |
| | 601 | @memcpy(dest[0..copy_len], buffer_contents[0..copy_len]); |
| | 602 | if (dest.len - copy_len == 0) { |
| | 603 | @branchHint(.likely); |
| | 604 | r.seek += copy_len; |
| | 605 | return buffer.len; |
| | 606 | } |
| | 607 | i += copy_len; |
| | 608 | r.end = 0; |
| | 609 | r.seek = 0; |
| 607 | const remaining = buffer[i..]; | 610 | const remaining = buffer[i..]; |
| 608 | var wrapper: Writer.VectorWrapper = .{ | 611 | const new_remaining_len = readVecInner(r, &.{}, remaining, remaining.len) catch |err| switch (err) { |
| 609 | .it = .{ | | |
| 610 | .first = remaining, | | |
| 611 | .last = r.buffer, | | |
| 612 | }, | | |
| 613 | .writer = .{ | | |
| 614 | .buffer = if (remaining.len >= r.buffer.len) remaining else r.buffer, | | |
| 615 | .vtable = Writer.VectorWrapper.vtable, | | |
| 616 | }, | | |
| 617 | }; | | |
| 618 | const n = r.vtable.stream(r, &wrapper.writer, .unlimited) catch |err| switch (err) { | | |
| 619 | error.WriteFailed => { | | |
| 620 | if (!wrapper.used) { | | |
| 621 | assert(r.seek == 0); | | |
| 622 | r.seek = remaining.len; | | |
| 623 | r.end = wrapper.writer.end; | | |
| 624 | @memcpy(remaining, r.buffer[0..remaining.len]); | | |
| 625 | } | | |
| 626 | return buffer.len; | | |
| 627 | }, | | |
| 628 | error.EndOfStream => return i, | 612 | error.EndOfStream => return i, |
| 629 | error.ReadFailed => return error.ReadFailed, | 613 | error.ReadFailed => return error.ReadFailed, |
| 630 | }; | 614 | }; |
| 631 | if (n < remaining.len) { | 615 | if (new_remaining_len == 0) return buffer.len; |
| 632 | i += n; | 616 | i += remaining.len - new_remaining_len; |
| 633 | continue; | | |
| 634 | } | | |
| 635 | r.end = n - remaining.len; | | |
| 636 | return buffer.len; | | |
| 637 | } | 617 | } |
| | 618 | return buffer.len; |
| 638 | } | 619 | } |
| 639 | | 620 | |
| 640 | /// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing | 621 | /// Fill `buffer` with the next `buffer.len` bytes from the stream, advancing |
| ... | @@ -1640,6 +1621,19 @@ test readSliceShort { | ... | @@ -1640,6 +1621,19 @@ test readSliceShort { |
| 1640 | try testing.expectEqual(0, try r.readSliceShort(&buf)); | 1621 | try testing.expectEqual(0, try r.readSliceShort(&buf)); |
| 1641 | } | 1622 | } |
| 1642 | | 1623 | |
| | 1624 | test "readSliceShort with smaller buffer than Reader" { |
| | 1625 | var reader_buf: [15]u8 = undefined; |
| | 1626 | const str = "This is a test"; |
| | 1627 | var one_byte_stream: testing.Reader = .init(&reader_buf, &.{ |
| | 1628 | .{ .buffer = str }, |
| | 1629 | }); |
| | 1630 | one_byte_stream.artificial_limit = .limited(1); |
| | 1631 | |
| | 1632 | var buf: [14]u8 = undefined; |
| | 1633 | try testing.expectEqual(14, try one_byte_stream.interface.readSliceShort(&buf)); |
| | 1634 | try testing.expectEqualStrings(str, &buf); |
| | 1635 | } |
| | 1636 | |
| 1643 | test readVec { | 1637 | test readVec { |
| 1644 | var r: Reader = .fixed(std.ascii.letters); | 1638 | var r: Reader = .fixed(std.ascii.letters); |
| 1645 | var flat_buffer: [52]u8 = undefined; | 1639 | var flat_buffer: [52]u8 = undefined; |
| ... | @@ -1702,33 +1696,13 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize { | ... | @@ -1702,33 +1696,13 @@ fn failingDiscard(r: *Reader, limit: Limit) Error!usize { |
| 1702 | } | 1696 | } |
| 1703 | | 1697 | |
| 1704 | test "readAlloc when the backing reader provides one byte at a time" { | 1698 | test "readAlloc when the backing reader provides one byte at a time" { |
| 1705 | const OneByteReader = struct { | | |
| 1706 | str: []const u8, | | |
| 1707 | i: usize, | | |
| 1708 | reader: Reader, | | |
| 1709 | | | |
| 1710 | fn stream(r: *Reader, w: *Writer, limit: Limit) StreamError!usize { | | |
| 1711 | assert(@intFromEnum(limit) >= 1); | | |
| 1712 | const self: *@This() = @fieldParentPtr("reader", r); | | |
| 1713 | if (self.str.len - self.i == 0) return error.EndOfStream; | | |
| 1714 | try w.writeByte(self.str[self.i]); | | |
| 1715 | self.i += 1; | | |
| 1716 | return 1; | | |
| 1717 | } | | |
| 1718 | }; | | |
| 1719 | const str = "This is a test"; | 1699 | const str = "This is a test"; |
| 1720 | var tiny_buffer: [1]u8 = undefined; | 1700 | var tiny_buffer: [1]u8 = undefined; |
| 1721 | var one_byte_stream: OneByteReader = .{ | 1701 | var one_byte_stream: testing.Reader = .init(&tiny_buffer, &.{ |
| 1722 | .str = str, | 1702 | .{ .buffer = str }, |
| 1723 | .i = 0, | 1703 | }); |
| 1724 | .reader = .{ | 1704 | one_byte_stream.artificial_limit = .limited(1); |
| 1725 | .buffer = &tiny_buffer, | 1705 | const res = try one_byte_stream.interface.allocRemaining(std.testing.allocator, .unlimited); |
| 1726 | .vtable = &.{ .stream = OneByteReader.stream }, | | |
| 1727 | .seek = 0, | | |
| 1728 | .end = 0, | | |
| 1729 | }, | | |
| 1730 | }; | | |
| 1731 | const res = try one_byte_stream.reader.allocRemaining(std.testing.allocator, .unlimited); | | |
| 1732 | defer std.testing.allocator.free(res); | 1706 | defer std.testing.allocator.free(res); |
| 1733 | try std.testing.expectEqualStrings(str, res); | 1707 | try std.testing.expectEqualStrings(str, res); |
| 1734 | } | 1708 | } |