diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-10-04 11:21:19 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-04 11:21:19 -0700 |
| commit | a306bfcd8eec166906ce2839bc7ff86ba6335376 (patch) | |
| tree | d1ae1ef50bb25e5a54829bcff658d922caa40edc /lib/std/io.zig | |
| parent | 4d1e8ef1eb1217e0a997b9bfa164142d83b01c0a (diff) | |
| parent | 9a09651019b24a32945f73dd7a69562f2cf31581 (diff) | |
| download | zig-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.zig | 255 |
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"); |
