zig/lib/std/io/PositionalReader.zig

65 lines
2.4 KiB
Zig

const std = @import("../std.zig");
const PositionalReader = @This();
const assert = std.debug.assert;
context: ?*anyopaque,
vtable: *const VTable,
pub const VTable = struct {
/// Writes bytes starting from `offset` to `bw`.
///
/// Returns the number of bytes written, which will be at minimum `0` and
/// at most `limit`. The number of bytes written, including zero, does not
/// indicate end of stream.
///
/// If the resource represented by the reader has an internal seek
/// position, it is not mutated.
///
/// The implementation should do a maximum of one underlying read call.
///
/// If `error.Unseekable` is returned, the resource cannot be used via a
/// positional reading interface.
read: *const fn (ctx: ?*anyopaque, bw: *std.io.BufferedWriter, limit: Limit, offset: u64) anyerror!Status,
/// Writes bytes starting from `offset` to `data`.
///
/// Returns the number of bytes written, which will be at minimum `0` and
/// at most `limit`. The number of bytes written, including zero, does not
/// indicate end of stream.
///
/// If the resource represented by the reader has an internal seek
/// position, it is not mutated.
///
/// The implementation should do a maximum of one underlying read call.
///
/// If `error.Unseekable` is returned, the resource cannot be used via a
/// positional reading interface.
readv: *const fn (ctx: ?*anyopaque, data: []const []u8, offset: u64) anyerror!Status,
};
pub const Len = std.io.Reader.Len;
pub const Status = std.io.Reader.Status;
pub const Limit = std.io.Reader.Limit;
pub fn read(pr: PositionalReader, bw: *std.io.BufferedWriter, limit: Limit, offset: u64) anyerror!Status {
return pr.vtable.read(pr.context, bw, limit, offset);
}
pub fn readv(pr: PositionalReader, data: []const []u8, offset: u64) anyerror!Status {
return pr.vtable.read(pr.context, data, offset);
}
/// Returns total number of bytes written to `w`.
///
/// May return `error.Unseekable`, indicating this function cannot be used to
/// read from the reader.
pub fn readAll(pr: PositionalReader, w: *std.io.BufferedWriter, start_offset: u64) anyerror!usize {
const readFn = pr.vtable.read;
var offset: u64 = start_offset;
while (true) {
const status = try readFn(pr.context, w, .none, offset);
offset += status.len;
if (status.end) return @intCast(offset - start_offset);
}
}