zig/lib/std/io/Reader/Limited.zig
2025-07-01 16:35:29 -07:00

57 lines
1.7 KiB
Zig

const Limited = @This();
const std = @import("../../std.zig");
const Reader = std.io.Reader;
const BufferedWriter = std.io.BufferedWriter;
const Limit = std.io.Limit;
unlimited_reader: Reader,
remaining: Limit,
pub fn reader(l: *Limited) Reader {
return .{
.context = l,
.vtable = &.{
.read = passthruRead,
.readVec = passthruReadVec,
.discard = passthruDiscard,
},
};
}
fn passthruRead(context: ?*anyopaque, bw: *BufferedWriter, limit: Limit) Reader.RwError!usize {
const l: *Limited = @alignCast(@ptrCast(context));
const combined_limit = limit.min(l.remaining);
const n = try l.unlimited_reader.read(bw, combined_limit);
l.remaining = l.remaining.subtract(n).?;
return n;
}
fn passthruDiscard(context: ?*anyopaque, limit: Limit) Reader.Error!usize {
const l: *Limited = @alignCast(@ptrCast(context));
const combined_limit = limit.min(l.remaining);
const n = try l.unlimited_reader.discard(combined_limit);
l.remaining = l.remaining.subtract(n).?;
return n;
}
fn passthruReadVec(context: ?*anyopaque, data: []const []u8) Reader.Error!usize {
const l: *Limited = @alignCast(@ptrCast(context));
if (data.len == 0) return 0;
if (data[0].len >= @intFromEnum(l.remaining)) {
const n = try l.unlimited_reader.readVec(&.{l.remaining.slice(data[0])});
l.remaining = l.remaining.subtract(n).?;
return n;
}
var total: usize = 0;
for (data, 0..) |buf, i| {
total += buf.len;
if (total > @intFromEnum(l.remaining)) {
const n = try l.unlimited_reader.readVec(data[0..i]);
l.remaining = l.remaining.subtract(n).?;
return n;
}
}
return 0;
}