| ... | @@ -481,7 +481,6 @@ pub fn readVecAll(r: *Reader, data: [][]u8) Error!void { | ... | @@ -481,7 +481,6 @@ pub fn readVecAll(r: *Reader, data: [][]u8) Error!void { |
| 481 | /// is returned instead. | 481 | /// is returned instead. |
| 482 | /// | 482 | /// |
| 483 | /// See also: | 483 | /// See also: |
| 484 | /// * `peek` | | |
| 485 | /// * `toss` | 484 | /// * `toss` |
| 486 | pub fn peek(r: *Reader, n: usize) Error![]u8 { | 485 | pub fn peek(r: *Reader, n: usize) Error![]u8 { |
| 487 | try r.fill(n); | 486 | try r.fill(n); |
| ... | @@ -732,7 +731,7 @@ pub const DelimiterError = error{ | ... | @@ -732,7 +731,7 @@ pub const DelimiterError = error{ |
| 732 | }; | 731 | }; |
| 733 | | 732 | |
| 734 | /// Returns a slice of the next bytes of buffered data from the stream until | 733 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 735 | /// `sentinel` is found, advancing the seek position. | 734 | /// `sentinel` is found, advancing the seek position past the sentinel. |
| 736 | /// | 735 | /// |
| 737 | /// Returned slice has a sentinel. | 736 | /// Returned slice has a sentinel. |
| 738 | /// | 737 | /// |
| ... | @@ -765,7 +764,7 @@ pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel | ... | @@ -765,7 +764,7 @@ pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel |
| 765 | } | 764 | } |
| 766 | | 765 | |
| 767 | /// Returns a slice of the next bytes of buffered data from the stream until | 766 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 768 | /// `delimiter` is found, advancing the seek position. | 767 | /// `delimiter` is found, advancing the seek position past the delimiter. |
| 769 | /// | 768 | /// |
| 770 | /// Returned slice includes the delimiter as the last byte. | 769 | /// Returned slice includes the delimiter as the last byte. |
| 771 | /// | 770 | /// |
| ... | @@ -818,7 +817,8 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | ... | @@ -818,7 +817,8 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 818 | } | 817 | } |
| 819 | | 818 | |
| 820 | /// Returns a slice of the next bytes of buffered data from the stream until | 819 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 821 | /// `delimiter` is found, advancing the seek position up to the delimiter. | 820 | /// `delimiter` is found, advancing the seek position up to (but not past) |
| | 821 | /// the delimiter. |
| 822 | /// | 822 | /// |
| 823 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent | 823 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent |
| 824 | /// to a delimiter, unless it would result in a length 0 return value, in which | 824 | /// to a delimiter, unless it would result in a length 0 return value, in which |
| ... | @@ -832,20 +832,13 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | ... | @@ -832,20 +832,13 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 832 | /// Invalidates previously returned values from `peek`. | 832 | /// Invalidates previously returned values from `peek`. |
| 833 | /// | 833 | /// |
| 834 | /// See also: | 834 | /// See also: |
| | 835 | /// * `takeDelimiter` |
| 835 | /// * `takeDelimiterInclusive` | 836 | /// * `takeDelimiterInclusive` |
| 836 | /// * `peekDelimiterExclusive` | 837 | /// * `peekDelimiterExclusive` |
| 837 | pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | 838 | pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 838 | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { | 839 | const result = try r.peekDelimiterExclusive(delimiter); |
| 839 | error.EndOfStream => { | | |
| 840 | const remaining = r.buffer[r.seek..r.end]; | | |
| 841 | if (remaining.len == 0) return error.EndOfStream; | | |
| 842 | r.toss(remaining.len); | | |
| 843 | return remaining; | | |
| 844 | }, | | |
| 845 | else => |e| return e, | | |
| 846 | }; | | |
| 847 | r.toss(result.len); | 840 | r.toss(result.len); |
| 848 | return result[0 .. result.len - 1]; | 841 | return result; |
| 849 | } | 842 | } |
| 850 | | 843 | |
| 851 | /// Returns a slice of the next bytes of buffered data from the stream until | 844 | /// Returns a slice of the next bytes of buffered data from the stream until |
| ... | @@ -866,7 +859,7 @@ pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | ... | @@ -866,7 +859,7 @@ pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 866 | /// * `takeDelimiterInclusive` | 859 | /// * `takeDelimiterInclusive` |
| 867 | /// * `takeDelimiterExclusive` | 860 | /// * `takeDelimiterExclusive` |
| 868 | pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong }!?[]u8 { | 861 | pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong }!?[]u8 { |
| 869 | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { | 862 | const inclusive = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { |
| 870 | error.EndOfStream => { | 863 | error.EndOfStream => { |
| 871 | const remaining = r.buffer[r.seek..r.end]; | 864 | const remaining = r.buffer[r.seek..r.end]; |
| 872 | if (remaining.len == 0) return null; | 865 | if (remaining.len == 0) return null; |
| ... | @@ -875,8 +868,8 @@ pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong | ... | @@ -875,8 +868,8 @@ pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong |
| 875 | }, | 868 | }, |
| 876 | else => |e| return e, | 869 | else => |e| return e, |
| 877 | }; | 870 | }; |
| 878 | r.toss(result.len + 1); | 871 | r.toss(inclusive.len); |
| 879 | return result[0 .. result.len - 1]; | 872 | return inclusive[0 .. inclusive.len - 1]; |
| 880 | } | 873 | } |
| 881 | | 874 | |
| 882 | /// Returns a slice of the next bytes of buffered data from the stream until | 875 | /// Returns a slice of the next bytes of buffered data from the stream until |
| ... | @@ -1403,6 +1396,9 @@ test peekSentinel { | ... | @@ -1403,6 +1396,9 @@ test peekSentinel { |
| 1403 | var r: Reader = .fixed("ab\nc"); | 1396 | var r: Reader = .fixed("ab\nc"); |
| 1404 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); | 1397 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); |
| 1405 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); | 1398 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); |
| | 1399 | r.toss(3); |
| | 1400 | try testing.expectError(error.EndOfStream, r.peekSentinel('\n')); |
| | 1401 | try testing.expectEqualStrings("c", try r.peek(1)); |
| 1406 | } | 1402 | } |
| 1407 | | 1403 | |
| 1408 | test takeDelimiterInclusive { | 1404 | test takeDelimiterInclusive { |
| ... | @@ -1417,22 +1413,52 @@ test peekDelimiterInclusive { | ... | @@ -1417,22 +1413,52 @@ test peekDelimiterInclusive { |
| 1417 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); | 1413 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); |
| 1418 | r.toss(3); | 1414 | r.toss(3); |
| 1419 | try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); | 1415 | try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); |
| | 1416 | try testing.expectEqualStrings("c", try r.peek(1)); |
| 1420 | } | 1417 | } |
| 1421 | | 1418 | |
| 1422 | test takeDelimiterExclusive { | 1419 | test takeDelimiterExclusive { |
| 1423 | var r: Reader = .fixed("ab\nc"); | 1420 | var r: Reader = .fixed("ab\nc"); |
| | 1421 | |
| 1424 | try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); | 1422 | try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); |
| | 1423 | try testing.expectEqualStrings("", try r.takeDelimiterExclusive('\n')); |
| | 1424 | try testing.expectEqualStrings("", try r.takeDelimiterExclusive('\n')); |
| | 1425 | try testing.expectEqualStrings("\n", try r.take(1)); |
| | 1426 | |
| 1425 | try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); | 1427 | try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); |
| 1426 | try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); | 1428 | try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); |
| 1427 | } | 1429 | } |
| 1428 | | 1430 | |
| 1429 | test peekDelimiterExclusive { | 1431 | test peekDelimiterExclusive { |
| 1430 | var r: Reader = .fixed("ab\nc"); | 1432 | var r: Reader = .fixed("ab\nc"); |
| | 1433 | |
| 1431 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); | 1434 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); |
| 1432 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); | 1435 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); |
| 1433 | r.toss(3); | 1436 | r.toss(2); |
| | 1437 | try testing.expectEqualStrings("", try r.peekDelimiterExclusive('\n')); |
| | 1438 | try testing.expectEqualStrings("\n", try r.take(1)); |
| | 1439 | |
| 1434 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); | 1440 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); |
| 1435 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); | 1441 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); |
| | 1442 | r.toss(1); |
| | 1443 | try testing.expectError(error.EndOfStream, r.peekDelimiterExclusive('\n')); |
| | 1444 | } |
| | 1445 | |
| | 1446 | test takeDelimiter { |
| | 1447 | var r: Reader = .fixed("ab\nc\n\nd"); |
| | 1448 | try testing.expectEqualStrings("ab", (try r.takeDelimiter('\n')).?); |
| | 1449 | try testing.expectEqualStrings("c", (try r.takeDelimiter('\n')).?); |
| | 1450 | try testing.expectEqualStrings("", (try r.takeDelimiter('\n')).?); |
| | 1451 | try testing.expectEqualStrings("d", (try r.takeDelimiter('\n')).?); |
| | 1452 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| | 1453 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| | 1454 | |
| | 1455 | r = .fixed("ab\nc\n\nd\n"); // one trailing newline does not affect behavior |
| | 1456 | try testing.expectEqualStrings("ab", (try r.takeDelimiter('\n')).?); |
| | 1457 | try testing.expectEqualStrings("c", (try r.takeDelimiter('\n')).?); |
| | 1458 | try testing.expectEqualStrings("", (try r.takeDelimiter('\n')).?); |
| | 1459 | try testing.expectEqualStrings("d", (try r.takeDelimiter('\n')).?); |
| | 1460 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| | 1461 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| 1436 | } | 1462 | } |
| 1437 | | 1463 | |
| 1438 | test streamDelimiter { | 1464 | test streamDelimiter { |