| ... | ... | @@ -689,3 +689,67 @@ pub fn containsAggregate(comptime T: type, haystack: []const T, needle: T) bool |
| 689 | 689 | } |
| 690 | 690 | return false; |
| 691 | 691 | } |
| 692 | |
| 693 | pub const AnyReader = struct { |
| 694 | readFn: *const fn (*anyopaque, []u8) anyerror!usize, |
| 695 | state: *anyopaque, |
| 696 | |
| 697 | pub fn from(reader: anytype) AnyReader { |
| 698 | const R = @TypeOf(reader); |
| 699 | const ctx = reader.context; |
| 700 | const Ctx = @TypeOf(ctx); |
| 701 | comptime std.debug.assert(std.meta.trait.is(.Pointer)(Ctx)); |
| 702 | const S = struct { |
| 703 | fn foo(s: *anyopaque, buffer: []u8) anyerror!usize { |
| 704 | const r = R{ .context = @ptrCast(@alignCast(s)) }; |
| 705 | return r.read(buffer); |
| 706 | } |
| 707 | }; |
| 708 | return .{ |
| 709 | .readFn = S.foo, |
| 710 | .state = ctx, |
| 711 | }; |
| 712 | } |
| 713 | |
| 714 | pub fn read(r: AnyReader, buffer: []u8) anyerror!usize { |
| 715 | return r.readFn(r.state, buffer); |
| 716 | } |
| 717 | |
| 718 | pub fn readByte(self: AnyReader) !u8 { |
| 719 | var result: [1]u8 = undefined; |
| 720 | const amt_read = try self.read(result[0..]); |
| 721 | if (amt_read < 1) return error.EndOfStream; |
| 722 | return result[0]; |
| 723 | } |
| 724 | |
| 725 | pub fn readInt(self: AnyReader, comptime T: type, endian: std.builtin.Endian) !T { |
| 726 | const bytes = try self.readBytesNoEof(@as(u16, @intCast((@as(u17, @typeInfo(T).Int.bits) + 7) / 8))); |
| 727 | return std.mem.readInt(T, &bytes, endian); |
| 728 | } |
| 729 | |
| 730 | pub fn readBytesNoEof(self: AnyReader, comptime num_bytes: usize) ![num_bytes]u8 { |
| 731 | var bytes: [num_bytes]u8 = undefined; |
| 732 | try self.readNoEof(&bytes); |
| 733 | return bytes; |
| 734 | } |
| 735 | |
| 736 | pub fn readNoEof(self: AnyReader, buf: []u8) !void { |
| 737 | const amt_read = try self.readAll(buf); |
| 738 | if (amt_read < buf.len) return error.EndOfStream; |
| 739 | } |
| 740 | |
| 741 | pub fn readAll(self: AnyReader, buffer: []u8) !usize { |
| 742 | return self.readAtLeast(buffer, buffer.len); |
| 743 | } |
| 744 | |
| 745 | pub fn readAtLeast(self: AnyReader, buffer: []u8, len: usize) !usize { |
| 746 | assert(len <= buffer.len); |
| 747 | var index: usize = 0; |
| 748 | while (index < len) { |
| 749 | const amt = try self.read(buffer[index..]); |
| 750 | if (amt == 0) break; |
| 751 | index += amt; |
| 752 | } |
| 753 | return index; |
| 754 | } |
| 755 | }; |