authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-10-11 22:41:06 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2023-10-11 22:41:06 -07:00
log8570068896254aa160278e6a552a0124e675f69d
treee4dc78c6052ededc00ae4304461bf50813ddef5b
parentfde7165927efa40fb5ab392c171dcfb06396e5cb

add AnyReader


1 files changed, 64 insertions(+), 0 deletions(-)

src/lib.zig+64
......@@ -689,3 +689,67 @@ pub fn containsAggregate(comptime T: type, haystack: []const T, needle: T) bool
689689 }
690690 return false;
691691}
692
693pub 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};