| ... | @@ -107,16 +107,16 @@ pub fn Reader( | ... | @@ -107,16 +107,16 @@ pub fn Reader( |
| 107 | ) !void { | 107 | ) !void { |
| 108 | array_list.shrinkRetainingCapacity(0); | 108 | array_list.shrinkRetainingCapacity(0); |
| 109 | while (true) { | 109 | while (true) { |
| | 110 | if (array_list.items.len == max_size) { |
| | 111 | return error.StreamTooLong; |
| | 112 | } |
| | 113 | |
| 110 | var byte: u8 = try self.readByte(); | 114 | var byte: u8 = try self.readByte(); |
| 111 | | 115 | |
| 112 | if (byte == delimiter) { | 116 | if (byte == delimiter) { |
| 113 | return; | 117 | return; |
| 114 | } | 118 | } |
| 115 | | 119 | |
| 116 | if (array_list.items.len == max_size) { | | |
| 117 | return error.StreamTooLong; | | |
| 118 | } | | |
| 119 | | | |
| 120 | try array_list.append(byte); | 120 | try array_list.append(byte); |
| 121 | } | 121 | } |
| 122 | } | 122 | } |
| ... | @@ -139,17 +139,20 @@ pub fn Reader( | ... | @@ -139,17 +139,20 @@ pub fn Reader( |
| 139 | | 139 | |
| 140 | /// Reads from the stream until specified byte is found. If the buffer is not | 140 | /// Reads from the stream until specified byte is found. If the buffer is not |
| 141 | /// large enough to hold the entire contents, `error.StreamTooLong` is returned. | 141 | /// large enough to hold the entire contents, `error.StreamTooLong` is returned. |
| | 142 | /// If end-of-stream is found, `error.EndOfStream` is returned. |
| 142 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The | 143 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The |
| 143 | /// delimiter byte is not included in the returned slice. | 144 | /// delimiter byte is written to the output buffer but is not included |
| | 145 | /// in the returned slice. |
| 144 | pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) ![]u8 { | 146 | pub fn readUntilDelimiter(self: Self, buf: []u8, delimiter: u8) ![]u8 { |
| 145 | var index: usize = 0; | 147 | var index: usize = 0; |
| 146 | while (true) { | 148 | while (true) { |
| | 149 | if (index >= buf.len) return error.StreamTooLong; |
| | 150 | |
| 147 | const byte = try self.readByte(); | 151 | const byte = try self.readByte(); |
| | 152 | buf[index] = byte; |
| 148 | | 153 | |
| 149 | if (byte == delimiter) return buf[0..index]; | 154 | if (byte == delimiter) return buf[0..index]; |
| 150 | if (index >= buf.len) return error.StreamTooLong; | | |
| 151 | | 155 | |
| 152 | buf[index] = byte; | | |
| 153 | index += 1; | 156 | index += 1; |
| 154 | } | 157 | } |
| 155 | } | 158 | } |
| ... | @@ -185,10 +188,13 @@ pub fn Reader( | ... | @@ -185,10 +188,13 @@ pub fn Reader( |
| 185 | /// If end-of-stream is found, returns the rest of the stream. If this | 188 | /// If end-of-stream is found, returns the rest of the stream. If this |
| 186 | /// function is called again after that, returns null. | 189 | /// function is called again after that, returns null. |
| 187 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The | 190 | /// Returns a slice of the stream data, with ptr equal to `buf.ptr`. The |
| 188 | /// delimiter byte is not included in the returned slice. | 191 | /// delimiter byte is written to the output buffer but is not included |
| | 192 | /// in the returned slice. |
| 189 | pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) !?[]u8 { | 193 | pub fn readUntilDelimiterOrEof(self: Self, buf: []u8, delimiter: u8) !?[]u8 { |
| 190 | var index: usize = 0; | 194 | var index: usize = 0; |
| 191 | while (true) { | 195 | while (true) { |
| | 196 | if (index >= buf.len) return error.StreamTooLong; |
| | 197 | |
| 192 | const byte = self.readByte() catch |err| switch (err) { | 198 | const byte = self.readByte() catch |err| switch (err) { |
| 193 | error.EndOfStream => { | 199 | error.EndOfStream => { |
| 194 | if (index == 0) { | 200 | if (index == 0) { |
| ... | @@ -199,11 +205,10 @@ pub fn Reader( | ... | @@ -199,11 +205,10 @@ pub fn Reader( |
| 199 | }, | 205 | }, |
| 200 | else => |e| return e, | 206 | else => |e| return e, |
| 201 | }; | 207 | }; |
| | 208 | buf[index] = byte; |
| 202 | | 209 | |
| 203 | if (byte == delimiter) return buf[0..index]; | 210 | if (byte == delimiter) return buf[0..index]; |
| 204 | if (index >= buf.len) return error.StreamTooLong; | | |
| 205 | | 211 | |
| 206 | buf[index] = byte; | | |
| 207 | index += 1; | 212 | index += 1; |
| 208 | } | 213 | } |
| 209 | } | 214 | } |
| ... | @@ -363,3 +368,272 @@ test "Reader.skipBytes" { | ... | @@ -363,3 +368,272 @@ test "Reader.skipBytes" { |
| 363 | try reader.skipBytes(0, .{}); | 368 | try reader.skipBytes(0, .{}); |
| 364 | try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{})); | 369 | try testing.expectError(error.EndOfStream, reader.skipBytes(1, .{})); |
| 365 | } | 370 | } |
| | 371 | |
| | 372 | test "Reader.readUntilDelimiterArrayList returns ArrayLists with bytes read until the delimiter, then EndOfStream" { |
| | 373 | const a = std.testing.allocator; |
| | 374 | var list = std.ArrayList(u8).init(a); |
| | 375 | defer list.deinit(); |
| | 376 | |
| | 377 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); |
| | 378 | |
| | 379 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); |
| | 380 | try std.testing.expectEqualStrings("0000", list.items); |
| | 381 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); |
| | 382 | try std.testing.expectEqualStrings("1234", list.items); |
| | 383 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5)); |
| | 384 | } |
| | 385 | |
| | 386 | test "Reader.readUntilDelimiterArrayList returns an empty ArrayList" { |
| | 387 | const a = std.testing.allocator; |
| | 388 | var list = std.ArrayList(u8).init(a); |
| | 389 | defer list.deinit(); |
| | 390 | |
| | 391 | const reader = std.io.fixedBufferStream("\n").reader(); |
| | 392 | |
| | 393 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); |
| | 394 | try std.testing.expectEqualStrings("", list.items); |
| | 395 | } |
| | 396 | |
| | 397 | test "Reader.readUntilDelimiterArrayList returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { |
| | 398 | const a = std.testing.allocator; |
| | 399 | var list = std.ArrayList(u8).init(a); |
| | 400 | defer list.deinit(); |
| | 401 | |
| | 402 | const reader = std.io.fixedBufferStream("1234567\n").reader(); |
| | 403 | |
| | 404 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterArrayList(&list, '\n', 5)); |
| | 405 | try std.testing.expectEqualStrings("12345", list.items); |
| | 406 | try reader.readUntilDelimiterArrayList(&list, '\n', 5); |
| | 407 | try std.testing.expectEqualStrings("67", list.items); |
| | 408 | } |
| | 409 | |
| | 410 | test "Reader.readUntilDelimiterArrayList returns EndOfStream" { |
| | 411 | const a = std.testing.allocator; |
| | 412 | var list = std.ArrayList(u8).init(a); |
| | 413 | defer list.deinit(); |
| | 414 | |
| | 415 | const reader = std.io.fixedBufferStream("1234").reader(); |
| | 416 | |
| | 417 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterArrayList(&list, '\n', 5)); |
| | 418 | try std.testing.expectEqualStrings("1234", list.items); |
| | 419 | } |
| | 420 | |
| | 421 | test "Reader.readUntilDelimiterAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" { |
| | 422 | const a = std.testing.allocator; |
| | 423 | |
| | 424 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); |
| | 425 | |
| | 426 | { |
| | 427 | var result = try reader.readUntilDelimiterAlloc(a, '\n', 5); |
| | 428 | defer a.free(result); |
| | 429 | try std.testing.expectEqualStrings("0000", result); |
| | 430 | } |
| | 431 | |
| | 432 | { |
| | 433 | var result = try reader.readUntilDelimiterAlloc(a, '\n', 5); |
| | 434 | defer a.free(result); |
| | 435 | try std.testing.expectEqualStrings("1234", result); |
| | 436 | } |
| | 437 | |
| | 438 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5)); |
| | 439 | } |
| | 440 | |
| | 441 | test "Reader.readUntilDelimiterAlloc returns an empty ArrayList" { |
| | 442 | const a = std.testing.allocator; |
| | 443 | |
| | 444 | const reader = std.io.fixedBufferStream("\n").reader(); |
| | 445 | |
| | 446 | { |
| | 447 | var result = try reader.readUntilDelimiterAlloc(a, '\n', 5); |
| | 448 | defer a.free(result); |
| | 449 | try std.testing.expectEqualStrings("", result); |
| | 450 | } |
| | 451 | } |
| | 452 | |
| | 453 | test "Reader.readUntilDelimiterAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { |
| | 454 | const a = std.testing.allocator; |
| | 455 | |
| | 456 | const reader = std.io.fixedBufferStream("1234567\n").reader(); |
| | 457 | |
| | 458 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterAlloc(a, '\n', 5)); |
| | 459 | |
| | 460 | var result = try reader.readUntilDelimiterAlloc(a, '\n', 5); |
| | 461 | defer a.free(result); |
| | 462 | try std.testing.expectEqualStrings("67", result); |
| | 463 | } |
| | 464 | |
| | 465 | test "Reader.readUntilDelimiterAlloc returns EndOfStream" { |
| | 466 | const a = std.testing.allocator; |
| | 467 | |
| | 468 | const reader = std.io.fixedBufferStream("1234").reader(); |
| | 469 | |
| | 470 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiterAlloc(a, '\n', 5)); |
| | 471 | } |
| | 472 | |
| | 473 | test "Reader.readUntilDelimiter returns bytes read until the delimiter" { |
| | 474 | var buf: [5]u8 = undefined; |
| | 475 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); |
| | 476 | try std.testing.expectEqualStrings("0000", try reader.readUntilDelimiter(&buf, '\n')); |
| | 477 | try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n')); |
| | 478 | } |
| | 479 | |
| | 480 | test "Reader.readUntilDelimiter returns an empty string" { |
| | 481 | var buf: [5]u8 = undefined; |
| | 482 | const reader = std.io.fixedBufferStream("\n").reader(); |
| | 483 | try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n')); |
| | 484 | } |
| | 485 | |
| | 486 | test "Reader.readUntilDelimiter returns StreamTooLong, then an empty string" { |
| | 487 | var buf: [5]u8 = undefined; |
| | 488 | const reader = std.io.fixedBufferStream("12345\n").reader(); |
| | 489 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| | 490 | try std.testing.expectEqualStrings("", try reader.readUntilDelimiter(&buf, '\n')); |
| | 491 | } |
| | 492 | |
| | 493 | test "Reader.readUntilDelimiter returns StreamTooLong, then bytes read until the delimiter" { |
| | 494 | var buf: [5]u8 = undefined; |
| | 495 | const reader = std.io.fixedBufferStream("1234567\n").reader(); |
| | 496 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| | 497 | try std.testing.expectEqualStrings("67", try reader.readUntilDelimiter(&buf, '\n')); |
| | 498 | } |
| | 499 | |
| | 500 | test "Reader.readUntilDelimiter returns EndOfStream" { |
| | 501 | var buf: [5]u8 = undefined; |
| | 502 | const reader = std.io.fixedBufferStream("").reader(); |
| | 503 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| | 504 | } |
| | 505 | |
| | 506 | test "Reader.readUntilDelimiter returns bytes read until delimiter, then EndOfStream" { |
| | 507 | var buf: [5]u8 = undefined; |
| | 508 | const reader = std.io.fixedBufferStream("1234\n").reader(); |
| | 509 | try std.testing.expectEqualStrings("1234", try reader.readUntilDelimiter(&buf, '\n')); |
| | 510 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| | 511 | } |
| | 512 | |
| | 513 | test "Reader.readUntilDelimiter returns EndOfStream" { |
| | 514 | var buf: [5]u8 = undefined; |
| | 515 | const reader = std.io.fixedBufferStream("1234").reader(); |
| | 516 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| | 517 | } |
| | 518 | |
| | 519 | test "Reader.readUntilDelimiter returns StreamTooLong, then EndOfStream" { |
| | 520 | var buf: [5]u8 = undefined; |
| | 521 | const reader = std.io.fixedBufferStream("12345").reader(); |
| | 522 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| | 523 | try std.testing.expectError(error.EndOfStream, reader.readUntilDelimiter(&buf, '\n')); |
| | 524 | } |
| | 525 | |
| | 526 | test "Reader.readUntilDelimiter writes all bytes read to the output buffer" { |
| | 527 | var buf: [5]u8 = undefined; |
| | 528 | const reader = std.io.fixedBufferStream("0000\n12345").reader(); |
| | 529 | _ = try reader.readUntilDelimiter(&buf, '\n'); |
| | 530 | try std.testing.expectEqualStrings("0000\n", &buf); |
| | 531 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiter(&buf, '\n')); |
| | 532 | try std.testing.expectEqualStrings("12345", &buf); |
| | 533 | } |
| | 534 | |
| | 535 | test "Reader.readUntilDelimiterOrEofAlloc returns ArrayLists with bytes read until the delimiter, then EndOfStream" { |
| | 536 | const a = std.testing.allocator; |
| | 537 | |
| | 538 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); |
| | 539 | |
| | 540 | { |
| | 541 | var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; |
| | 542 | defer a.free(result); |
| | 543 | try std.testing.expectEqualStrings("0000", result); |
| | 544 | } |
| | 545 | |
| | 546 | { |
| | 547 | var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; |
| | 548 | defer a.free(result); |
| | 549 | try std.testing.expectEqualStrings("1234", result); |
| | 550 | } |
| | 551 | |
| | 552 | try std.testing.expect((try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)) == null); |
| | 553 | } |
| | 554 | |
| | 555 | test "Reader.readUntilDelimiterOrEofAlloc returns an empty ArrayList" { |
| | 556 | const a = std.testing.allocator; |
| | 557 | |
| | 558 | const reader = std.io.fixedBufferStream("\n").reader(); |
| | 559 | |
| | 560 | { |
| | 561 | var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; |
| | 562 | defer a.free(result); |
| | 563 | try std.testing.expectEqualStrings("", result); |
| | 564 | } |
| | 565 | } |
| | 566 | |
| | 567 | test "Reader.readUntilDelimiterOrEofAlloc returns StreamTooLong, then an ArrayList with bytes read until the delimiter" { |
| | 568 | const a = std.testing.allocator; |
| | 569 | |
| | 570 | const reader = std.io.fixedBufferStream("1234567\n").reader(); |
| | 571 | |
| | 572 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)); |
| | 573 | |
| | 574 | var result = (try reader.readUntilDelimiterOrEofAlloc(a, '\n', 5)).?; |
| | 575 | defer a.free(result); |
| | 576 | try std.testing.expectEqualStrings("67", result); |
| | 577 | } |
| | 578 | |
| | 579 | test "Reader.readUntilDelimiterOrEof returns bytes read until the delimiter" { |
| | 580 | var buf: [5]u8 = undefined; |
| | 581 | const reader = std.io.fixedBufferStream("0000\n1234\n").reader(); |
| | 582 | try std.testing.expectEqualStrings("0000", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 583 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 584 | } |
| | 585 | |
| | 586 | test "Reader.readUntilDelimiterOrEof returns an empty string" { |
| | 587 | var buf: [5]u8 = undefined; |
| | 588 | const reader = std.io.fixedBufferStream("\n").reader(); |
| | 589 | try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 590 | } |
| | 591 | |
| | 592 | test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then an empty string" { |
| | 593 | var buf: [5]u8 = undefined; |
| | 594 | const reader = std.io.fixedBufferStream("12345\n").reader(); |
| | 595 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| | 596 | try std.testing.expectEqualStrings("", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 597 | } |
| | 598 | |
| | 599 | test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then bytes read until the delimiter" { |
| | 600 | var buf: [5]u8 = undefined; |
| | 601 | const reader = std.io.fixedBufferStream("1234567\n").reader(); |
| | 602 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| | 603 | try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 604 | } |
| | 605 | |
| | 606 | test "Reader.readUntilDelimiterOrEof returns null" { |
| | 607 | var buf: [5]u8 = undefined; |
| | 608 | const reader = std.io.fixedBufferStream("").reader(); |
| | 609 | try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null); |
| | 610 | } |
| | 611 | |
| | 612 | test "Reader.readUntilDelimiterOrEof returns bytes read until delimiter, then null" { |
| | 613 | var buf: [5]u8 = undefined; |
| | 614 | const reader = std.io.fixedBufferStream("1234\n").reader(); |
| | 615 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 616 | try std.testing.expect((try reader.readUntilDelimiterOrEof(&buf, '\n')) == null); |
| | 617 | } |
| | 618 | |
| | 619 | test "Reader.readUntilDelimiterOrEof returns bytes read until end-of-stream" { |
| | 620 | var buf: [5]u8 = undefined; |
| | 621 | const reader = std.io.fixedBufferStream("1234").reader(); |
| | 622 | try std.testing.expectEqualStrings("1234", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 623 | } |
| | 624 | |
| | 625 | test "Reader.readUntilDelimiterOrEof returns StreamTooLong, then bytes read until end-of-stream" { |
| | 626 | var buf: [5]u8 = undefined; |
| | 627 | const reader = std.io.fixedBufferStream("1234567").reader(); |
| | 628 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| | 629 | try std.testing.expectEqualStrings("67", (try reader.readUntilDelimiterOrEof(&buf, '\n')).?); |
| | 630 | } |
| | 631 | |
| | 632 | test "Reader.readUntilDelimiterOrEof writes all bytes read to the output buffer" { |
| | 633 | var buf: [5]u8 = undefined; |
| | 634 | const reader = std.io.fixedBufferStream("0000\n12345").reader(); |
| | 635 | _ = try reader.readUntilDelimiterOrEof(&buf, '\n'); |
| | 636 | try std.testing.expectEqualStrings("0000\n", &buf); |
| | 637 | try std.testing.expectError(error.StreamTooLong, reader.readUntilDelimiterOrEof(&buf, '\n')); |
| | 638 | try std.testing.expectEqualStrings("12345", &buf); |
| | 639 | } |