| ... | ... | @@ -445,7 +445,7 @@ pub fn toss(r: *Reader, n: usize) void { |
| 445 | 445 | } |
| 446 | 446 | |
| 447 | 447 | /// Equivalent to `toss(r.bufferedLen())`. |
| 448 | | pub fn tossAll(r: *Reader) void { |
| 448 | pub fn tossBuffered(r: *Reader) void { |
| 449 | 449 | r.seek = 0; |
| 450 | 450 | r.end = 0; |
| 451 | 451 | } |
| ... | ... | @@ -557,7 +557,7 @@ pub fn discardShort(r: *Reader, n: usize) ShortError!usize { |
| 557 | 557 | /// See also: |
| 558 | 558 | /// * `peek` |
| 559 | 559 | /// * `readSliceShort` |
| 560 | | pub fn readSlice(r: *Reader, buffer: []u8) Error!void { |
| 560 | pub fn readSliceAll(r: *Reader, buffer: []u8) Error!void { |
| 561 | 561 | const n = try readSliceShort(r, buffer); |
| 562 | 562 | if (n != buffer.len) return error.EndOfStream; |
| 563 | 563 | } |
| ... | ... | @@ -571,7 +571,7 @@ pub fn readSlice(r: *Reader, buffer: []u8) Error!void { |
| 571 | 571 | /// only if the stream reached the end. |
| 572 | 572 | /// |
| 573 | 573 | /// See also: |
| 574 | | /// * `readSlice` |
| 574 | /// * `readSliceAll` |
| 575 | 575 | pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize { |
| 576 | 576 | const in_buffer = r.buffer[r.seek..r.end]; |
| 577 | 577 | const copy_len = @min(buffer.len, in_buffer.len); |
| ... | ... | @@ -630,7 +630,7 @@ pub fn readSliceShort(r: *Reader, buffer: []u8) ShortError!usize { |
| 630 | 630 | /// comptime-known and matches host endianness. |
| 631 | 631 | /// |
| 632 | 632 | /// See also: |
| 633 | | /// * `readSlice` |
| 633 | /// * `readSliceAll` |
| 634 | 634 | /// * `readSliceEndianAlloc` |
| 635 | 635 | pub inline fn readSliceEndian( |
| 636 | 636 | r: *Reader, |
| ... | ... | @@ -638,7 +638,7 @@ pub inline fn readSliceEndian( |
| 638 | 638 | buffer: []Elem, |
| 639 | 639 | endian: std.builtin.Endian, |
| 640 | 640 | ) Error!void { |
| 641 | | try readSlice(r, @ptrCast(buffer)); |
| 641 | try readSliceAll(r, @ptrCast(buffer)); |
| 642 | 642 | if (native_endian != endian) for (buffer) |*elem| std.mem.byteSwapAllFields(Elem, elem); |
| 643 | 643 | } |
| 644 | 644 | |
| ... | ... | @@ -655,15 +655,16 @@ pub inline fn readSliceEndianAlloc( |
| 655 | 655 | ) ReadAllocError![]Elem { |
| 656 | 656 | const dest = try allocator.alloc(Elem, len); |
| 657 | 657 | errdefer allocator.free(dest); |
| 658 | | try readSlice(r, @ptrCast(dest)); |
| 658 | try readSliceAll(r, @ptrCast(dest)); |
| 659 | 659 | if (native_endian != endian) for (dest) |*elem| std.mem.byteSwapAllFields(Elem, elem); |
| 660 | 660 | return dest; |
| 661 | 661 | } |
| 662 | 662 | |
| 663 | | pub fn readSliceAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 { |
| 663 | /// Shortcut for calling `readSliceAll` with a buffer provided by `allocator`. |
| 664 | pub fn readAlloc(r: *Reader, allocator: Allocator, len: usize) ReadAllocError![]u8 { |
| 664 | 665 | const dest = try allocator.alloc(u8, len); |
| 665 | 666 | errdefer allocator.free(dest); |
| 666 | | try readSlice(r, dest); |
| 667 | try readSliceAll(r, dest); |
| 667 | 668 | return dest; |
| 668 | 669 | } |
| 669 | 670 | |
| ... | ... | @@ -1092,6 +1093,7 @@ pub fn takeVarInt(r: *Reader, comptime Int: type, endian: std.builtin.Endian, n: |
| 1092 | 1093 | /// |
| 1093 | 1094 | /// See also: |
| 1094 | 1095 | /// * `peekStruct` |
| 1096 | /// * `takeStructEndian` |
| 1095 | 1097 | pub fn takeStruct(r: *Reader, comptime T: type) Error!*align(1) T { |
| 1096 | 1098 | // Only extern and packed structs have defined in-memory layout. |
| 1097 | 1099 | comptime assert(@typeInfo(T).@"struct".layout != .auto); |
| ... | ... | @@ -1104,6 +1106,7 @@ pub fn takeStruct(r: *Reader, comptime T: type) Error!*align(1) T { |
| 1104 | 1106 | /// |
| 1105 | 1107 | /// See also: |
| 1106 | 1108 | /// * `takeStruct` |
| 1109 | /// * `peekStructEndian` |
| 1107 | 1110 | pub fn peekStruct(r: *Reader, comptime T: type) Error!*align(1) T { |
| 1108 | 1111 | // Only extern and packed structs have defined in-memory layout. |
| 1109 | 1112 | comptime assert(@typeInfo(T).@"struct".layout != .auto); |
| ... | ... | @@ -1114,6 +1117,10 @@ pub fn peekStruct(r: *Reader, comptime T: type) Error!*align(1) T { |
| 1114 | 1117 | /// |
| 1115 | 1118 | /// This function is inline to avoid referencing `std.mem.byteSwapAllFields` |
| 1116 | 1119 | /// when `endian` is comptime-known and matches the host endianness. |
| 1120 | /// |
| 1121 | /// See also: |
| 1122 | /// * `takeStruct` |
| 1123 | /// * `peekStructEndian` |
| 1117 | 1124 | pub inline fn takeStructEndian(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T { |
| 1118 | 1125 | var res = (try r.takeStruct(T)).*; |
| 1119 | 1126 | if (native_endian != endian) std.mem.byteSwapAllFields(T, &res); |
| ... | ... | @@ -1124,6 +1131,10 @@ pub inline fn takeStructEndian(r: *Reader, comptime T: type, endian: std.builtin |
| 1124 | 1131 | /// |
| 1125 | 1132 | /// This function is inline to avoid referencing `std.mem.byteSwapAllFields` |
| 1126 | 1133 | /// when `endian` is comptime-known and matches the host endianness. |
| 1134 | /// |
| 1135 | /// See also: |
| 1136 | /// * `takeStructEndian` |
| 1137 | /// * `peekStruct` |
| 1127 | 1138 | pub inline fn peekStructEndian(r: *Reader, comptime T: type, endian: std.builtin.Endian) Error!T { |
| 1128 | 1139 | var res = (try r.peekStruct(T)).*; |
| 1129 | 1140 | if (native_endian != endian) std.mem.byteSwapAllFields(T, &res); |
| ... | ... | @@ -1489,25 +1500,47 @@ test takeInt { |
| 1489 | 1500 | |
| 1490 | 1501 | test takeVarInt { |
| 1491 | 1502 | var r: Reader = .fixed(&.{ 0x12, 0x34, 0x56 }); |
| 1492 | | std.debug.print("{x}", .{r.buffer}); |
| 1493 | 1503 | try testing.expectEqual(0x123456, try r.takeVarInt(u64, .big, 3)); |
| 1494 | 1504 | try testing.expectError(error.EndOfStream, r.takeVarInt(u16, .little, 1)); |
| 1495 | 1505 | } |
| 1496 | 1506 | |
| 1497 | 1507 | test takeStruct { |
| 1498 | | return error.Unimplemented; |
| 1508 | var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 }); |
| 1509 | const S = extern struct { a: u8, b: u16 }; |
| 1510 | switch (native_endian) { |
| 1511 | .little => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.takeStruct(S)).*), |
| 1512 | .big => try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.takeStruct(S)).*), |
| 1513 | } |
| 1514 | try testing.expectError(error.EndOfStream, r.takeStruct(S)); |
| 1499 | 1515 | } |
| 1500 | 1516 | |
| 1501 | 1517 | test peekStruct { |
| 1502 | | return error.Unimplemented; |
| 1518 | var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 }); |
| 1519 | const S = extern struct { a: u8, b: u16 }; |
| 1520 | switch (native_endian) { |
| 1521 | .little => { |
| 1522 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStruct(S)).*); |
| 1523 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), (try r.peekStruct(S)).*); |
| 1524 | }, |
| 1525 | .big => { |
| 1526 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStruct(S)).*); |
| 1527 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), (try r.peekStruct(S)).*); |
| 1528 | }, |
| 1529 | } |
| 1503 | 1530 | } |
| 1504 | 1531 | |
| 1505 | 1532 | test takeStructEndian { |
| 1506 | | return error.Unimplemented; |
| 1533 | var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 }); |
| 1534 | const S = extern struct { a: u8, b: u16 }; |
| 1535 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), try r.takeStructEndian(S, .big)); |
| 1536 | try testing.expectError(error.EndOfStream, r.takeStructEndian(S, .little)); |
| 1507 | 1537 | } |
| 1508 | 1538 | |
| 1509 | 1539 | test peekStructEndian { |
| 1510 | | return error.Unimplemented; |
| 1540 | var r: Reader = .fixed(&.{ 0x12, 0x00, 0x34, 0x56 }); |
| 1541 | const S = extern struct { a: u8, b: u16 }; |
| 1542 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x3456 }), try r.peekStructEndian(S, .big)); |
| 1543 | try testing.expectEqual(@as(S, .{ .a = 0x12, .b = 0x5634 }), try r.peekStructEndian(S, .little)); |
| 1511 | 1544 | } |
| 1512 | 1545 | |
| 1513 | 1546 | test takeEnum { |
| ... | ... | @@ -1519,15 +1552,46 @@ test takeEnum { |
| 1519 | 1552 | } |
| 1520 | 1553 | |
| 1521 | 1554 | test takeLeb128 { |
| 1522 | | return error.Unimplemented; |
| 1555 | var r: Reader = .fixed("\xc7\x9f\x7f\x80"); |
| 1556 | try testing.expectEqual(-12345, try r.takeLeb128(i64)); |
| 1557 | try testing.expectEqual(0x80, try r.peekByte()); |
| 1558 | try testing.expectError(error.EndOfStream, r.takeLeb128(i64)); |
| 1523 | 1559 | } |
| 1524 | 1560 | |
| 1525 | 1561 | test readSliceShort { |
| 1526 | | return error.Unimplemented; |
| 1562 | var r: Reader = .fixed("HelloFren"); |
| 1563 | var buf: [5]u8 = undefined; |
| 1564 | try testing.expectEqual(5, try r.readSliceShort(&buf)); |
| 1565 | try testing.expectEqualStrings("Hello", buf[0..5]); |
| 1566 | try testing.expectEqual(4, try r.readSliceShort(&buf)); |
| 1567 | try testing.expectEqualStrings("Fren", buf[0..4]); |
| 1568 | try testing.expectEqual(0, try r.readSliceShort(&buf)); |
| 1527 | 1569 | } |
| 1528 | 1570 | |
| 1529 | 1571 | test readVec { |
| 1530 | | return error.Unimplemented; |
| 1572 | var r: Reader = .fixed(std.ascii.letters); |
| 1573 | var flat_buffer: [52]u8 = undefined; |
| 1574 | var bufs: [2][]u8 = .{ |
| 1575 | flat_buffer[0..26], |
| 1576 | flat_buffer[26..], |
| 1577 | }; |
| 1578 | // Short reads are possible with this function but not with fixed. |
| 1579 | try testing.expectEqual(26 * 2, try r.readVec(&bufs)); |
| 1580 | try testing.expectEqualStrings(std.ascii.letters[0..26], bufs[0]); |
| 1581 | try testing.expectEqualStrings(std.ascii.letters[26..], bufs[1]); |
| 1582 | } |
| 1583 | |
| 1584 | test readVecLimit { |
| 1585 | var r: Reader = .fixed(std.ascii.letters); |
| 1586 | var flat_buffer: [52]u8 = undefined; |
| 1587 | var bufs: [2][]u8 = .{ |
| 1588 | flat_buffer[0..26], |
| 1589 | flat_buffer[26..], |
| 1590 | }; |
| 1591 | // Short reads are possible with this function but not with fixed. |
| 1592 | try testing.expectEqual(50, try r.readVecLimit(&bufs, .limited(50))); |
| 1593 | try testing.expectEqualStrings(std.ascii.letters[0..26], bufs[0]); |
| 1594 | try testing.expectEqualStrings(std.ascii.letters[26..50], bufs[1][0..24]); |
| 1531 | 1595 | } |
| 1532 | 1596 | |
| 1533 | 1597 | test "expected error.EndOfStream" { |