aboutsummaryrefslogtreecommitdiff
path: root/lib/std/io.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-10-04 11:21:19 -0700
committerGitHub <noreply@github.com>2023-10-04 11:21:19 -0700
commita306bfcd8eec166906ce2839bc7ff86ba6335376 (patch)
treed1ae1ef50bb25e5a54829bcff658d922caa40edc /lib/std/io.zig
parent4d1e8ef1eb1217e0a997b9bfa164142d83b01c0a (diff)
parent9a09651019b24a32945f73dd7a69562f2cf31581 (diff)
downloadzig-a306bfcd8eec166906ce2839bc7ff86ba6335376.tar.gz
zig-a306bfcd8eec166906ce2839bc7ff86ba6335376.zip
Merge pull request #17344 from ziglang/type-erased-reader
std: add type-erased reader; base GenericReader on it
Diffstat (limited to 'lib/std/io.zig')
-rw-r--r--lib/std/io.zig255
1 files changed, 252 insertions, 3 deletions
diff --git a/lib/std/io.zig b/lib/std/io.zig
index e7a4476c0f..64ed9f757e 100644
--- a/lib/std/io.zig
+++ b/lib/std/io.zig
@@ -10,6 +10,7 @@ const fs = std.fs;
const mem = std.mem;
const meta = std.meta;
const File = std.fs.File;
+const Allocator = std.mem.Allocator;
pub const Mode = enum {
/// I/O operates normally, waiting for the operating system syscalls to complete.
@@ -105,7 +106,255 @@ pub fn getStdIn() File {
};
}
-pub const Reader = @import("io/reader.zig").Reader;
+pub fn GenericReader(
+ comptime Context: type,
+ comptime ReadError: type,
+ /// Returns the number of bytes read. It may be less than buffer.len.
+ /// If the number of bytes read is 0, it means end of stream.
+ /// End of stream is not an error condition.
+ comptime readFn: fn (context: Context, buffer: []u8) ReadError!usize,
+) type {
+ return struct {
+ context: Context,
+
+ pub const Error = ReadError;
+ pub const NoEofError = ReadError || error{
+ EndOfStream,
+ };
+
+ pub inline fn read(self: Self, buffer: []u8) Error!usize {
+ return readFn(self.context, buffer);
+ }
+
+ pub inline fn readAll(self: Self, buffer: []u8) Error!usize {
+ return @errorCast(self.any().readAll(buffer));
+ }
+
+ pub inline fn readAtLeast(self: Self, buffer: []u8, len: usize) Error!usize {
+ return @errorCast(self.any().readAtLeast(buffer, len));
+ }
+
+ pub inline fn readNoEof(self: Self, buf: []u8) NoEofError!void {
+ return @errorCast(self.any().readNoEof(buf));
+ }
+
+ pub inline fn readAllArrayList(
+ self: Self,
+ array_list: *std.ArrayList(u8),
+ max_append_size: usize,
+ ) (error{StreamTooLong} || Error)!void {
+ return @errorCast(self.any().readAllArrayList(array_list, max_append_size));
+ }
+
+ pub inline fn readAllArrayListAligned(
+ self: Self,
+ comptime alignment: ?u29,
+ array_list: *std.ArrayListAligned(u8, alignment),
+ max_append_size: usize,
+ ) (error{StreamTooLong} || Error)!void {
+ return @errorCast(self.any().readAllArrayListAligned(
+ alignment,
+ array_list,
+ max_append_size,
+ ));
+ }
+
+ pub inline fn readAllAlloc(
+ self: Self,
+ allocator: Allocator,
+ max_size: usize,
+ ) (Error || error{StreamTooLong})![]u8 {
+ return @errorCast(self.any().readAllAlloc(allocator, max_size));
+ }
+
+ pub inline fn readUntilDelimiterArrayList(
+ self: Self,
+ array_list: *std.ArrayList(u8),
+ delimiter: u8,
+ max_size: usize,
+ ) (NoEofError || error{StreamTooLong})!void {
+ return @errorCast(self.any().readUntilDelimiterArrayList(
+ array_list,
+ delimiter,
+ max_size,
+ ));
+ }
+
+ pub inline fn readUntilDelimiterAlloc(
+ self: Self,
+ allocator: Allocator,
+ delimiter: u8,
+ max_size: usize,
+ ) (NoEofError || error{StreamTooLong})![]u8 {
+ return @errorCast(self.any().readUntilDelimiterAlloc(
+ allocator,
+ delimiter,
+ max_size,
+ ));
+ }
+
+ pub inline fn readUntilDelimiter(
+ self: Self,
+ buf: []u8,
+ delimiter: u8,
+ ) (NoEofError || error{StreamTooLong})![]u8 {
+ return @errorCast(self.any().readUntilDelimiter(buf, delimiter));
+ }
+
+ pub inline fn readUntilDelimiterOrEofAlloc(
+ self: Self,
+ allocator: Allocator,
+ delimiter: u8,
+ max_size: usize,
+ ) (Error || error{StreamTooLong})!?[]u8 {
+ return @errorCast(self.any().readUntilDelimiterOrEofAlloc(
+ allocator,
+ delimiter,
+ max_size,
+ ));
+ }
+
+ pub inline fn readUntilDelimiterOrEof(
+ self: Self,
+ buf: []u8,
+ delimiter: u8,
+ ) (Error || error{StreamTooLong})!?[]u8 {
+ return @errorCast(self.any().readUntilDelimiterOrEof(buf, delimiter));
+ }
+
+ pub inline fn streamUntilDelimiter(
+ self: Self,
+ writer: anytype,
+ delimiter: u8,
+ optional_max_size: ?usize,
+ ) (NoEofError || error{StreamTooLong} || @TypeOf(writer).Error)!void {
+ return @errorCast(self.any().streamUntilDelimiter(
+ writer,
+ delimiter,
+ optional_max_size,
+ ));
+ }
+
+ pub inline fn skipUntilDelimiterOrEof(self: Self, delimiter: u8) Error!void {
+ return @errorCast(self.any().skipUntilDelimiterOrEof(delimiter));
+ }
+
+ pub inline fn readByte(self: Self) NoEofError!u8 {
+ return @errorCast(self.any().readByte());
+ }
+
+ pub inline fn readByteSigned(self: Self) NoEofError!i8 {
+ return @errorCast(self.any().readByteSigned());
+ }
+
+ pub inline fn readBytesNoEof(
+ self: Self,
+ comptime num_bytes: usize,
+ ) NoEofError![num_bytes]u8 {
+ return @errorCast(self.any().readBytesNoEof(num_bytes));
+ }
+
+ pub inline fn readIntoBoundedBytes(
+ self: Self,
+ comptime num_bytes: usize,
+ bounded: *std.BoundedArray(u8, num_bytes),
+ ) Error!void {
+ return @errorCast(self.any().readIntoBoundedBytes(num_bytes, bounded));
+ }
+
+ pub inline fn readBoundedBytes(
+ self: Self,
+ comptime num_bytes: usize,
+ ) Error!std.BoundedArray(u8, num_bytes) {
+ return @errorCast(self.any().readBoundedBytes(num_bytes));
+ }
+
+ pub inline fn readIntNative(self: Self, comptime T: type) NoEofError!T {
+ return @errorCast(self.any().readIntNative(T));
+ }
+
+ pub inline fn readIntForeign(self: Self, comptime T: type) NoEofError!T {
+ return @errorCast(self.any().readIntForeign(T));
+ }
+
+ pub inline fn readIntLittle(self: Self, comptime T: type) NoEofError!T {
+ return @errorCast(self.any().readIntLittle(T));
+ }
+
+ pub inline fn readIntBig(self: Self, comptime T: type) NoEofError!T {
+ return @errorCast(self.any().readIntBig(T));
+ }
+
+ pub inline fn readInt(self: Self, comptime T: type, endian: std.builtin.Endian) NoEofError!T {
+ return @errorCast(self.any().readInt(T, endian));
+ }
+
+ pub inline fn readVarInt(
+ self: Self,
+ comptime ReturnType: type,
+ endian: std.builtin.Endian,
+ size: usize,
+ ) NoEofError!ReturnType {
+ return @errorCast(self.any().readVarInt(ReturnType, endian, size));
+ }
+
+ pub const SkipBytesOptions = AnyReader.SkipBytesOptions;
+
+ pub inline fn skipBytes(
+ self: Self,
+ num_bytes: u64,
+ comptime options: SkipBytesOptions,
+ ) NoEofError!void {
+ return @errorCast(self.any().skipBytes(num_bytes, options));
+ }
+
+ pub inline fn isBytes(self: Self, slice: []const u8) Error!bool {
+ return @errorCast(self.any().isBytes(slice));
+ }
+
+ pub inline fn readStruct(self: Self, comptime T: type) NoEofError!T {
+ return @errorCast(self.any().readStruct(T));
+ }
+
+ pub inline fn readStructBig(self: Self, comptime T: type) NoEofError!T {
+ return @errorCast(self.any().readStructBig(T));
+ }
+
+ pub const ReadEnumError = Error || error{
+ /// An integer was read, but it did not match any of the tags in the supplied enum.
+ InvalidValue,
+ };
+
+ pub inline fn readEnum(
+ self: Self,
+ comptime Enum: type,
+ endian: std.builtin.Endian,
+ ) ReadEnumError!Enum {
+ return @errorCast(self.any().readEnum(Enum, endian));
+ }
+
+ pub inline fn any(self: *const Self) AnyReader {
+ return .{
+ .context = @ptrCast(&self.context),
+ .readFn = typeErasedReadFn,
+ };
+ }
+
+ const Self = @This();
+
+ fn typeErasedReadFn(context: *const anyopaque, buffer: []u8) anyerror!usize {
+ const ptr: *const Context = @alignCast(@ptrCast(context));
+ return readFn(ptr.*, buffer);
+ }
+ };
+}
+
+/// Deprecated; consider switching to `AnyReader` or use `GenericReader`
+/// to use previous API.
+pub const Reader = GenericReader;
+
+pub const AnyReader = @import("io/Reader.zig");
+
pub const Writer = @import("io/writer.zig").Writer;
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
@@ -168,7 +417,7 @@ test "null_writer" {
}
pub fn poll(
- allocator: std.mem.Allocator,
+ allocator: Allocator,
comptime StreamEnum: type,
files: PollFiles(StreamEnum),
) Poller(StreamEnum) {
@@ -418,6 +667,7 @@ pub fn PollFiles(comptime StreamEnum: type) type {
}
test {
+ _ = AnyReader;
_ = @import("io/bit_reader.zig");
_ = @import("io/bit_writer.zig");
_ = @import("io/buffered_atomic_file.zig");
@@ -427,7 +677,6 @@ test {
_ = @import("io/counting_writer.zig");
_ = @import("io/counting_reader.zig");
_ = @import("io/fixed_buffer_stream.zig");
- _ = @import("io/reader.zig");
_ = @import("io/writer.zig");
_ = @import("io/peek_stream.zig");
_ = @import("io/seekable_stream.zig");