| ... | ... | @@ -513,8 +513,8 @@ pub const HeadersParser = struct { |
| 513 | 513 | /// |
| 514 | 514 | /// If `skip` is true, the buffer will be unused and the body will be skipped. |
| 515 | 515 | /// |
| 516 | | /// See `std.http.Client.BufferedConnection for an example of `bconn`. |
| 517 | | pub fn read(r: *HeadersParser, bconn: anytype, buffer: []u8, skip: bool) !usize { |
| 516 | /// See `std.http.Client.BufferedConnection for an example of `conn`. |
| 517 | pub fn read(r: *HeadersParser, conn: anytype, buffer: []u8, skip: bool) !usize { |
| 518 | 518 | assert(r.state.isContent()); |
| 519 | 519 | if (r.done) return 0; |
| 520 | 520 | |
| ... | ... | @@ -526,10 +526,10 @@ pub const HeadersParser = struct { |
| 526 | 526 | const data_avail = r.next_chunk_length; |
| 527 | 527 | |
| 528 | 528 | if (skip) { |
| 529 | | try bconn.fill(); |
| 529 | try conn.fill(); |
| 530 | 530 | |
| 531 | | const nread = @min(bconn.peek().len, data_avail); |
| 532 | | bconn.clear(@intCast(u16, nread)); |
| 531 | const nread = @min(conn.peek().len, data_avail); |
| 532 | conn.drop(@intCast(u16, nread)); |
| 533 | 533 | r.next_chunk_length -= nread; |
| 534 | 534 | |
| 535 | 535 | if (r.next_chunk_length == 0) r.done = true; |
| ... | ... | @@ -539,7 +539,7 @@ pub const HeadersParser = struct { |
| 539 | 539 | const out_avail = buffer.len; |
| 540 | 540 | |
| 541 | 541 | const can_read = @intCast(usize, @min(data_avail, out_avail)); |
| 542 | | const nread = try bconn.read(buffer[0..can_read]); |
| 542 | const nread = try conn.read(buffer[0..can_read]); |
| 543 | 543 | r.next_chunk_length -= nread; |
| 544 | 544 | |
| 545 | 545 | if (r.next_chunk_length == 0) r.done = true; |
| ... | ... | @@ -548,15 +548,15 @@ pub const HeadersParser = struct { |
| 548 | 548 | } |
| 549 | 549 | }, |
| 550 | 550 | .chunk_data_suffix, .chunk_data_suffix_r, .chunk_head_size, .chunk_head_ext, .chunk_head_r => { |
| 551 | | try bconn.fill(); |
| 551 | try conn.fill(); |
| 552 | 552 | |
| 553 | | const i = r.findChunkedLen(bconn.peek()); |
| 554 | | bconn.clear(@intCast(u16, i)); |
| 553 | const i = r.findChunkedLen(conn.peek()); |
| 554 | conn.drop(@intCast(u16, i)); |
| 555 | 555 | |
| 556 | 556 | switch (r.state) { |
| 557 | 557 | .invalid => return error.HttpChunkInvalid, |
| 558 | 558 | .chunk_data => if (r.next_chunk_length == 0) { |
| 559 | | if (std.mem.eql(u8, bconn.peek(), "\r\n")) { |
| 559 | if (std.mem.eql(u8, conn.peek(), "\r\n")) { |
| 560 | 560 | r.state = .finished; |
| 561 | 561 | } else { |
| 562 | 562 | // The trailer section is formatted identically to the header section. |
| ... | ... | @@ -576,14 +576,14 @@ pub const HeadersParser = struct { |
| 576 | 576 | const out_avail = buffer.len - out_index; |
| 577 | 577 | |
| 578 | 578 | if (skip) { |
| 579 | | try bconn.fill(); |
| 579 | try conn.fill(); |
| 580 | 580 | |
| 581 | | const nread = @min(bconn.peek().len, data_avail); |
| 582 | | bconn.clear(@intCast(u16, nread)); |
| 581 | const nread = @min(conn.peek().len, data_avail); |
| 582 | conn.drop(@intCast(u16, nread)); |
| 583 | 583 | r.next_chunk_length -= nread; |
| 584 | 584 | } else { |
| 585 | 585 | const can_read = @intCast(usize, @min(data_avail, out_avail)); |
| 586 | | const nread = try bconn.read(buffer[out_index..][0..can_read]); |
| 586 | const nread = try conn.read(buffer[out_index..][0..can_read]); |
| 587 | 587 | r.next_chunk_length -= nread; |
| 588 | 588 | out_index += nread; |
| 589 | 589 | } |
| ... | ... | @@ -628,74 +628,74 @@ const MockBufferedConnection = struct { |
| 628 | 628 | start: u16 = 0, |
| 629 | 629 | end: u16 = 0, |
| 630 | 630 | |
| 631 | | pub fn fill(bconn: *MockBufferedConnection) ReadError!void { |
| 632 | | if (bconn.end != bconn.start) return; |
| 631 | pub fn fill(conn: *MockBufferedConnection) ReadError!void { |
| 632 | if (conn.end != conn.start) return; |
| 633 | 633 | |
| 634 | | const nread = try bconn.conn.read(bconn.buf[0..]); |
| 634 | const nread = try conn.conn.read(conn.buf[0..]); |
| 635 | 635 | if (nread == 0) return error.EndOfStream; |
| 636 | | bconn.start = 0; |
| 637 | | bconn.end = @truncate(u16, nread); |
| 636 | conn.start = 0; |
| 637 | conn.end = @truncate(u16, nread); |
| 638 | 638 | } |
| 639 | 639 | |
| 640 | | pub fn peek(bconn: *MockBufferedConnection) []const u8 { |
| 641 | | return bconn.buf[bconn.start..bconn.end]; |
| 640 | pub fn peek(conn: *MockBufferedConnection) []const u8 { |
| 641 | return conn.buf[conn.start..conn.end]; |
| 642 | 642 | } |
| 643 | 643 | |
| 644 | 644 | pub fn drop(conn: *MockBufferedConnection, num: u16) void { |
| 645 | 645 | conn.start += num; |
| 646 | 646 | } |
| 647 | 647 | |
| 648 | | pub fn readAtLeast(bconn: *MockBufferedConnection, buffer: []u8, len: usize) ReadError!usize { |
| 648 | pub fn readAtLeast(conn: *MockBufferedConnection, buffer: []u8, len: usize) ReadError!usize { |
| 649 | 649 | var out_index: u16 = 0; |
| 650 | 650 | while (out_index < len) { |
| 651 | | const available = bconn.end - bconn.start; |
| 651 | const available = conn.end - conn.start; |
| 652 | 652 | const left = buffer.len - out_index; |
| 653 | 653 | |
| 654 | 654 | if (available > 0) { |
| 655 | 655 | const can_read = @truncate(u16, @min(available, left)); |
| 656 | 656 | |
| 657 | | @memcpy(buffer[out_index..][0..can_read], bconn.buf[bconn.start..][0..can_read]); |
| 657 | @memcpy(buffer[out_index..][0..can_read], conn.buf[conn.start..][0..can_read]); |
| 658 | 658 | out_index += can_read; |
| 659 | | bconn.start += can_read; |
| 659 | conn.start += can_read; |
| 660 | 660 | |
| 661 | 661 | continue; |
| 662 | 662 | } |
| 663 | 663 | |
| 664 | | if (left > bconn.buf.len) { |
| 664 | if (left > conn.buf.len) { |
| 665 | 665 | // skip the buffer if the output is large enough |
| 666 | | return bconn.conn.read(buffer[out_index..]); |
| 666 | return conn.conn.read(buffer[out_index..]); |
| 667 | 667 | } |
| 668 | 668 | |
| 669 | | try bconn.fill(); |
| 669 | try conn.fill(); |
| 670 | 670 | } |
| 671 | 671 | |
| 672 | 672 | return out_index; |
| 673 | 673 | } |
| 674 | 674 | |
| 675 | | pub fn read(bconn: *MockBufferedConnection, buffer: []u8) ReadError!usize { |
| 676 | | return bconn.readAtLeast(buffer, 1); |
| 675 | pub fn read(conn: *MockBufferedConnection, buffer: []u8) ReadError!usize { |
| 676 | return conn.readAtLeast(buffer, 1); |
| 677 | 677 | } |
| 678 | 678 | |
| 679 | 679 | pub const ReadError = std.io.FixedBufferStream([]const u8).ReadError || error{EndOfStream}; |
| 680 | 680 | pub const Reader = std.io.Reader(*MockBufferedConnection, ReadError, read); |
| 681 | 681 | |
| 682 | | pub fn reader(bconn: *MockBufferedConnection) Reader { |
| 683 | | return Reader{ .context = bconn }; |
| 682 | pub fn reader(conn: *MockBufferedConnection) Reader { |
| 683 | return Reader{ .context = conn }; |
| 684 | 684 | } |
| 685 | 685 | |
| 686 | | pub fn writeAll(bconn: *MockBufferedConnection, buffer: []const u8) WriteError!void { |
| 687 | | return bconn.conn.writeAll(buffer); |
| 686 | pub fn writeAll(conn: *MockBufferedConnection, buffer: []const u8) WriteError!void { |
| 687 | return conn.conn.writeAll(buffer); |
| 688 | 688 | } |
| 689 | 689 | |
| 690 | | pub fn write(bconn: *MockBufferedConnection, buffer: []const u8) WriteError!usize { |
| 691 | | return bconn.conn.write(buffer); |
| 690 | pub fn write(conn: *MockBufferedConnection, buffer: []const u8) WriteError!usize { |
| 691 | return conn.conn.write(buffer); |
| 692 | 692 | } |
| 693 | 693 | |
| 694 | 694 | pub const WriteError = std.io.FixedBufferStream([]const u8).WriteError; |
| 695 | 695 | pub const Writer = std.io.Writer(*MockBufferedConnection, WriteError, write); |
| 696 | 696 | |
| 697 | | pub fn writer(bconn: *MockBufferedConnection) Writer { |
| 698 | | return Writer{ .context = bconn }; |
| 697 | pub fn writer(conn: *MockBufferedConnection) Writer { |
| 698 | return Writer{ .context = conn }; |
| 699 | 699 | } |
| 700 | 700 | }; |
| 701 | 701 | |
| ... | ... | @@ -753,12 +753,12 @@ test "HeadersParser.read length" { |
| 753 | 753 | const data = "GET / HTTP/1.1\r\nHost: localhost\r\nContent-Length: 5\r\n\r\nHello"; |
| 754 | 754 | var fbs = std.io.fixedBufferStream(data); |
| 755 | 755 | |
| 756 | | var bconn = MockBufferedConnection{ |
| 756 | var conn = MockBufferedConnection{ |
| 757 | 757 | .conn = fbs, |
| 758 | 758 | }; |
| 759 | 759 | |
| 760 | 760 | while (true) { // read headers |
| 761 | | try bconn.fill(); |
| 761 | try conn.fill(); |
| 762 | 762 | |
| 763 | 763 | const nchecked = try r.checkCompleteHead(std.testing.allocator, conn.peek()); |
| 764 | 764 | conn.drop(@intCast(u16, nchecked)); |
| ... | ... | @@ -769,7 +769,7 @@ test "HeadersParser.read length" { |
| 769 | 769 | var buf: [8]u8 = undefined; |
| 770 | 770 | |
| 771 | 771 | r.next_chunk_length = 5; |
| 772 | | const len = try r.read(&bconn, &buf, false); |
| 772 | const len = try r.read(&conn, &buf, false); |
| 773 | 773 | try std.testing.expectEqual(@as(usize, 5), len); |
| 774 | 774 | try std.testing.expectEqualStrings("Hello", buf[0..len]); |
| 775 | 775 | |
| ... | ... | @@ -784,12 +784,12 @@ test "HeadersParser.read chunked" { |
| 784 | 784 | const data = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n2\r\nHe\r\n2\r\nll\r\n1\r\no\r\n0\r\n\r\n"; |
| 785 | 785 | var fbs = std.io.fixedBufferStream(data); |
| 786 | 786 | |
| 787 | | var bconn = MockBufferedConnection{ |
| 787 | var conn = MockBufferedConnection{ |
| 788 | 788 | .conn = fbs, |
| 789 | 789 | }; |
| 790 | 790 | |
| 791 | 791 | while (true) { // read headers |
| 792 | | try bconn.fill(); |
| 792 | try conn.fill(); |
| 793 | 793 | |
| 794 | 794 | const nchecked = try r.checkCompleteHead(std.testing.allocator, conn.peek()); |
| 795 | 795 | conn.drop(@intCast(u16, nchecked)); |
| ... | ... | @@ -799,7 +799,7 @@ test "HeadersParser.read chunked" { |
| 799 | 799 | var buf: [8]u8 = undefined; |
| 800 | 800 | |
| 801 | 801 | r.state = .chunk_head_size; |
| 802 | | const len = try r.read(&bconn, &buf, false); |
| 802 | const len = try r.read(&conn, &buf, false); |
| 803 | 803 | try std.testing.expectEqual(@as(usize, 5), len); |
| 804 | 804 | try std.testing.expectEqualStrings("Hello", buf[0..len]); |
| 805 | 805 | |
| ... | ... | @@ -814,12 +814,12 @@ test "HeadersParser.read chunked trailer" { |
| 814 | 814 | const data = "GET / HTTP/1.1\r\nHost: localhost\r\n\r\n2\r\nHe\r\n2\r\nll\r\n1\r\no\r\n0\r\nContent-Type: text/plain\r\n\r\n"; |
| 815 | 815 | var fbs = std.io.fixedBufferStream(data); |
| 816 | 816 | |
| 817 | | var bconn = MockBufferedConnection{ |
| 817 | var conn = MockBufferedConnection{ |
| 818 | 818 | .conn = fbs, |
| 819 | 819 | }; |
| 820 | 820 | |
| 821 | 821 | while (true) { // read headers |
| 822 | | try bconn.fill(); |
| 822 | try conn.fill(); |
| 823 | 823 | |
| 824 | 824 | const nchecked = try r.checkCompleteHead(std.testing.allocator, conn.peek()); |
| 825 | 825 | conn.drop(@intCast(u16, nchecked)); |
| ... | ... | @@ -829,12 +829,12 @@ test "HeadersParser.read chunked trailer" { |
| 829 | 829 | var buf: [8]u8 = undefined; |
| 830 | 830 | |
| 831 | 831 | r.state = .chunk_head_size; |
| 832 | | const len = try r.read(&bconn, &buf, false); |
| 832 | const len = try r.read(&conn, &buf, false); |
| 833 | 833 | try std.testing.expectEqual(@as(usize, 5), len); |
| 834 | 834 | try std.testing.expectEqualStrings("Hello", buf[0..len]); |
| 835 | 835 | |
| 836 | 836 | while (true) { // read headers |
| 837 | | try bconn.fill(); |
| 837 | try conn.fill(); |
| 838 | 838 | |
| 839 | 839 | const nchecked = try r.checkCompleteHead(std.testing.allocator, conn.peek()); |
| 840 | 840 | conn.drop(@intCast(u16, nchecked)); |