authorgravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-05-31 14:45:21 -07:00
committergravatar for hello@nektro.netMeghan Denny <hello@nektro.net> 2026-05-31 14:45:21 -07:00
log93e7414f96aa2b27f3f0bf72f27967c83e6396ef
treed334d63445910c3b926a9b4c7e514df4f92ff57d
parent6fa4f951dc0c384f9ae10e2d698638b966de9f14
signaturebadge-check Signed by SSH key SHA256:4hHJbtBRU58AYXwjL7fkz2fnQHdiye8x1QpTCQ0sHNw

add LimitedReader


2 files changed, 75 insertions(+), 0 deletions(-)

limited_reader.zig created+73
...@@ -0,0 +1,73 @@
1const std = @import("std");
2const builtin = @import("builtin");
3const extras = @import("extras");
4const nio = @import("./nio.zig");
5
6const sys = switch (builtin.target.os.tag) {
7 .linux => @import("sys-linux"),
8 .macos => @import("sys-darwin"),
9 else => unreachable,
10};
11
12pub fn LimitedReader(ReaderType: type) type {
13 return struct {
14 backing_reader: ReaderType,
15 bytes_left: u64,
16
17 const Self = @This();
18
19 pub fn init(backing_reader: ReaderType, bytes_left: u64) Self {
20 return .{
21 .backing_reader = backing_reader,
22 .bytes_left = bytes_left,
23 };
24 }
25
26 const R = nio.Readable(@This(), ._var);
27 pub const readAll = R.readAll;
28 pub const readAtLeast = R.readAtLeast;
29 pub const readNoEof = R.readNoEof;
30 pub const readAllAlloc = R.readAllAlloc;
31 pub const readArray = R.readArray;
32 pub const readByte = R.readByte;
33 pub const readUntilDelimiterArrayList = R.readUntilDelimiterArrayList;
34 pub const readUntilDelimiterAlloc = R.readUntilDelimiterAlloc;
35 pub const readUntilDelimiterOrEofAlloc = R.readUntilDelimiterOrEofAlloc;
36 pub const readUntilDelimitersBuf = R.readUntilDelimitersBuf;
37 pub const readUntilDelimitersArrayList = R.readUntilDelimitersArrayList;
38 pub const readAlloc = R.readAlloc;
39 pub const readInt = R.readInt;
40 pub const readUntilDelimitersAlloc = R.readUntilDelimitersAlloc;
41 pub const readUntilDelimiterOrEof = R.readUntilDelimiterOrEof;
42 pub const readExpected = R.readExpected;
43 pub const skipBytes = R.skipBytes;
44 pub const skipUntilDelimiterOrEof = R.skipUntilDelimiterOrEof;
45
46 pub const ReadError = extras.Pointee(ReaderType).ReadError;
47
48 pub fn read(self: *Self, bytes: []u8) ReadError!usize {
49 const max_read = @min(self.bytes_left, bytes.len);
50 const n = try self.backing_reader.read(bytes[0..max_read]);
51 self.bytes_left -= n;
52 return n;
53 }
54 // pub fn readv(self: *Self, iovec: []sys.struct_iovec) ReadError!usize {
55 // const len = try self.backing_reader.readv(iovec);
56 // self.bytes_read += len;
57 // return len;
58 // }
59
60 pub fn anyReadable(self: *Self) nio.AnyReadable {
61 const S = struct {
62 fn read(s: *allowzero anyopaque, buffer: []u8) anyerror!usize {
63 const fbs: *Self = @ptrCast(@alignCast(s));
64 return fbs.read(buffer);
65 }
66 };
67 return .{
68 .vtable = &.{ .read = S.read },
69 .state = @ptrCast(self),
70 };
71 }
72 };
73}
nio.zig+2
...@@ -395,3 +395,5 @@ pub const NullWriter = @import("./null_writer.zig").NullWriter;...@@ -395,3 +395,5 @@ pub const NullWriter = @import("./null_writer.zig").NullWriter;
395pub const AllocatingWriter = @import("./allocating_writer.zig").AllocatingWriter;395pub const AllocatingWriter = @import("./allocating_writer.zig").AllocatingWriter;
396396
397pub const CountingReader = @import("./counting_reader.zig").CountingReader;397pub const CountingReader = @import("./counting_reader.zig").CountingReader;
398
399pub const LimitedReader = @import("./limited_reader.zig").LimitedReader;