| ... | @@ -689,3 +689,67 @@ pub fn containsAggregate(comptime T: type, haystack: []const T, needle: T) bool | ... | @@ -689,3 +689,67 @@ pub fn containsAggregate(comptime T: type, haystack: []const T, needle: T) bool |
| 689 | } | 689 | } |
| 690 | return false; | 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 | }; |