| ... | @@ -449,7 +449,6 @@ pub fn readVecAll(r: *Reader, data: [][]u8) Error!void { | ... | @@ -449,7 +449,6 @@ pub fn readVecAll(r: *Reader, data: [][]u8) Error!void { |
| 449 | /// is returned instead. | 449 | /// is returned instead. |
| 450 | /// | 450 | /// |
| 451 | /// See also: | 451 | /// See also: |
| 452 | /// * `peek` | | |
| 453 | /// * `toss` | 452 | /// * `toss` |
| 454 | pub fn peek(r: *Reader, n: usize) Error![]u8 { | 453 | pub fn peek(r: *Reader, n: usize) Error![]u8 { |
| 455 | try r.fill(n); | 454 | try r.fill(n); |
| ... | @@ -700,7 +699,7 @@ pub const DelimiterError = error{ | ... | @@ -700,7 +699,7 @@ pub const DelimiterError = error{ |
| 700 | }; | 699 | }; |
| 701 | | 700 | |
| 702 | /// Returns a slice of the next bytes of buffered data from the stream until | 701 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 703 | /// `sentinel` is found, advancing the seek position. | 702 | /// `sentinel` is found, advancing the seek position past the sentinel. |
| 704 | /// | 703 | /// |
| 705 | /// Returned slice has a sentinel. | 704 | /// Returned slice has a sentinel. |
| 706 | /// | 705 | /// |
| ... | @@ -733,7 +732,7 @@ pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel | ... | @@ -733,7 +732,7 @@ pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel |
| 733 | } | 732 | } |
| 734 | | 733 | |
| 735 | /// Returns a slice of the next bytes of buffered data from the stream until | 734 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 736 | /// `delimiter` is found, advancing the seek position. | 735 | /// `delimiter` is found, advancing the seek position past the delimiter. |
| 737 | /// | 736 | /// |
| 738 | /// Returned slice includes the delimiter as the last byte. | 737 | /// Returned slice includes the delimiter as the last byte. |
| 739 | /// | 738 | /// |
| ... | @@ -786,7 +785,8 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | ... | @@ -786,7 +785,8 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 786 | } | 785 | } |
| 787 | | 786 | |
| 788 | /// Returns a slice of the next bytes of buffered data from the stream until | 787 | /// Returns a slice of the next bytes of buffered data from the stream until |
| 789 | /// `delimiter` is found, advancing the seek position. | 788 | /// `delimiter` is found, advancing the seek position up to (but not past) |
| | 789 | /// the delimiter. |
| 790 | /// | 790 | /// |
| 791 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent | 791 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent |
| 792 | /// to a delimiter, unless it would result in a length 0 return value, in which | 792 | /// to a delimiter, unless it would result in a length 0 return value, in which |
| ... | @@ -800,20 +800,44 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | ... | @@ -800,20 +800,44 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 800 | /// Invalidates previously returned values from `peek`. | 800 | /// Invalidates previously returned values from `peek`. |
| 801 | /// | 801 | /// |
| 802 | /// See also: | 802 | /// See also: |
| | 803 | /// * `takeDelimiter` |
| 803 | /// * `takeDelimiterInclusive` | 804 | /// * `takeDelimiterInclusive` |
| 804 | /// * `peekDelimiterExclusive` | 805 | /// * `peekDelimiterExclusive` |
| 805 | pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { | 806 | pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 806 | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { | 807 | const result = try r.peekDelimiterExclusive(delimiter); |
| | 808 | r.toss(result.len); |
| | 809 | return result; |
| | 810 | } |
| | 811 | |
| | 812 | /// Returns a slice of the next bytes of buffered data from the stream until |
| | 813 | /// `delimiter` is found, advancing the seek position past the delimiter. |
| | 814 | /// |
| | 815 | /// Returned slice excludes the delimiter. End-of-stream is treated equivalent |
| | 816 | /// to a delimiter, unless it would result in a length 0 return value, in which |
| | 817 | /// case `null` is returned instead. |
| | 818 | /// |
| | 819 | /// If the delimiter is not found within a number of bytes matching the |
| | 820 | /// capacity of this `Reader`, `error.StreamTooLong` is returned. In |
| | 821 | /// such case, the stream state is unmodified as if this function was never |
| | 822 | /// called. |
| | 823 | /// |
| | 824 | /// Invalidates previously returned values from `peek`. |
| | 825 | /// |
| | 826 | /// See also: |
| | 827 | /// * `takeDelimiterInclusive` |
| | 828 | /// * `takeDelimiterExclusive` |
| | 829 | pub fn takeDelimiter(r: *Reader, delimiter: u8) error{ ReadFailed, StreamTooLong }!?[]u8 { |
| | 830 | const inclusive = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { |
| 807 | error.EndOfStream => { | 831 | error.EndOfStream => { |
| 808 | const remaining = r.buffer[r.seek..r.end]; | 832 | const remaining = r.buffer[r.seek..r.end]; |
| 809 | if (remaining.len == 0) return error.EndOfStream; | 833 | if (remaining.len == 0) return null; |
| 810 | r.toss(remaining.len); | 834 | r.toss(remaining.len); |
| 811 | return remaining; | 835 | return remaining; |
| 812 | }, | 836 | }, |
| 813 | else => |e| return e, | 837 | else => |e| return e, |
| 814 | }; | 838 | }; |
| 815 | r.toss(result.len); | 839 | r.toss(inclusive.len); |
| 816 | return result[0 .. result.len - 1]; | 840 | return inclusive[0 .. inclusive.len - 1]; |
| 817 | } | 841 | } |
| 818 | | 842 | |
| 819 | /// Returns a slice of the next bytes of buffered data from the stream until | 843 | /// Returns a slice of the next bytes of buffered data from the stream until |
| ... | @@ -1336,6 +1360,9 @@ test peekSentinel { | ... | @@ -1336,6 +1360,9 @@ test peekSentinel { |
| 1336 | var r: Reader = .fixed("ab\nc"); | 1360 | var r: Reader = .fixed("ab\nc"); |
| 1337 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); | 1361 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); |
| 1338 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); | 1362 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); |
| | 1363 | r.toss(3); |
| | 1364 | try testing.expectError(error.EndOfStream, r.peekSentinel('\n')); |
| | 1365 | try testing.expectEqualStrings("c", try r.peek(1)); |
| 1339 | } | 1366 | } |
| 1340 | | 1367 | |
| 1341 | test takeDelimiterInclusive { | 1368 | test takeDelimiterInclusive { |
| ... | @@ -1350,22 +1377,52 @@ test peekDelimiterInclusive { | ... | @@ -1350,22 +1377,52 @@ test peekDelimiterInclusive { |
| 1350 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); | 1377 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); |
| 1351 | r.toss(3); | 1378 | r.toss(3); |
| 1352 | try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); | 1379 | try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); |
| | 1380 | try testing.expectEqualStrings("c", try r.peek(1)); |
| 1353 | } | 1381 | } |
| 1354 | | 1382 | |
| 1355 | test takeDelimiterExclusive { | 1383 | test takeDelimiterExclusive { |
| 1356 | var r: Reader = .fixed("ab\nc"); | 1384 | var r: Reader = .fixed("ab\nc"); |
| | 1385 | |
| 1357 | try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); | 1386 | try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); |
| | 1387 | try testing.expectEqualStrings("", try r.takeDelimiterExclusive('\n')); |
| | 1388 | try testing.expectEqualStrings("", try r.takeDelimiterExclusive('\n')); |
| | 1389 | try testing.expectEqualStrings("\n", try r.take(1)); |
| | 1390 | |
| 1358 | try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); | 1391 | try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); |
| 1359 | try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); | 1392 | try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); |
| 1360 | } | 1393 | } |
| 1361 | | 1394 | |
| 1362 | test peekDelimiterExclusive { | 1395 | test peekDelimiterExclusive { |
| 1363 | var r: Reader = .fixed("ab\nc"); | 1396 | var r: Reader = .fixed("ab\nc"); |
| | 1397 | |
| 1364 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); | 1398 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); |
| 1365 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); | 1399 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); |
| 1366 | r.toss(3); | 1400 | r.toss(2); |
| | 1401 | try testing.expectEqualStrings("", try r.peekDelimiterExclusive('\n')); |
| | 1402 | try testing.expectEqualStrings("\n", try r.take(1)); |
| | 1403 | |
| 1367 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); | 1404 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); |
| 1368 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); | 1405 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); |
| | 1406 | r.toss(1); |
| | 1407 | try testing.expectError(error.EndOfStream, r.peekDelimiterExclusive('\n')); |
| | 1408 | } |
| | 1409 | |
| | 1410 | test takeDelimiter { |
| | 1411 | var r: Reader = .fixed("ab\nc\n\nd"); |
| | 1412 | try testing.expectEqualStrings("ab", (try r.takeDelimiter('\n')).?); |
| | 1413 | try testing.expectEqualStrings("c", (try r.takeDelimiter('\n')).?); |
| | 1414 | try testing.expectEqualStrings("", (try r.takeDelimiter('\n')).?); |
| | 1415 | try testing.expectEqualStrings("d", (try r.takeDelimiter('\n')).?); |
| | 1416 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| | 1417 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| | 1418 | |
| | 1419 | r = .fixed("ab\nc\n\nd\n"); // one trailing newline does not affect behavior |
| | 1420 | try testing.expectEqualStrings("ab", (try r.takeDelimiter('\n')).?); |
| | 1421 | try testing.expectEqualStrings("c", (try r.takeDelimiter('\n')).?); |
| | 1422 | try testing.expectEqualStrings("", (try r.takeDelimiter('\n')).?); |
| | 1423 | try testing.expectEqualStrings("d", (try r.takeDelimiter('\n')).?); |
| | 1424 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| | 1425 | try testing.expectEqual(null, try r.takeDelimiter('\n')); |
| 1369 | } | 1426 | } |
| 1370 | | 1427 | |
| 1371 | test streamDelimiter { | 1428 | test streamDelimiter { |