mirror of
https://github.com/ziglang/zig.git
synced 2024-11-15 00:26:57 +00:00
Add type-erased writer and GenericWriter
This is a companion to #17344 to apply the same change to the `std.io.Writer` interface.
This commit is contained in:
parent
4dfca01de4
commit
e392c1a0b3
@ -265,7 +265,7 @@ set(ZIG_STAGE2_SOURCES
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/io/limited_reader.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/io/Reader.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/io/seekable_stream.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/io/writer.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/io/Writer.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/json.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/json/stringify.zig"
|
||||
"${CMAKE_SOURCE_DIR}/lib/std/leb128.zig"
|
||||
|
@ -333,13 +333,73 @@ pub fn GenericReader(
|
||||
};
|
||||
}
|
||||
|
||||
pub fn GenericWriter(
|
||||
comptime Context: type,
|
||||
comptime WriteError: type,
|
||||
comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
|
||||
) type {
|
||||
return struct {
|
||||
context: Context,
|
||||
|
||||
const Self = @This();
|
||||
pub const Error = WriteError;
|
||||
|
||||
pub inline fn write(self: Self, bytes: []const u8) Error!usize {
|
||||
return writeFn(self.context, bytes);
|
||||
}
|
||||
|
||||
pub inline fn writeAll(self: Self, bytes: []const u8) Error!void {
|
||||
return @errorCast(self.any().writeAll(bytes));
|
||||
}
|
||||
|
||||
pub inline fn print(self: Self, comptime format: []const u8, args: anytype) Error!void {
|
||||
return @errorCast(self.any().print(format, args));
|
||||
}
|
||||
|
||||
pub inline fn writeByte(self: Self, byte: u8) Error!void {
|
||||
return @errorCast(self.any().writeByte(byte));
|
||||
}
|
||||
|
||||
pub inline fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void {
|
||||
return @errorCast(self.any().writeByteNTimes(byte, n));
|
||||
}
|
||||
|
||||
pub inline fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) Error!void {
|
||||
return @errorCast(self.any().writeBytesNTimes(bytes, n));
|
||||
}
|
||||
|
||||
pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) Error!void {
|
||||
return @errorCast(self.any().writeInt(T, value, endian));
|
||||
}
|
||||
|
||||
pub inline fn writeStruct(self: Self, value: anytype) Error!void {
|
||||
return @errorCast(self.any().writeStruct(value));
|
||||
}
|
||||
|
||||
pub inline fn any(self: *const Self) AnyWriter {
|
||||
return .{
|
||||
.context = @ptrCast(&self.context),
|
||||
.writeFn = typeErasedWriteFn,
|
||||
};
|
||||
}
|
||||
|
||||
fn typeErasedWriteFn(context: *const anyopaque, bytes: []const u8) anyerror!usize {
|
||||
const ptr: *const Context = @alignCast(@ptrCast(context));
|
||||
return writeFn(ptr.*, bytes);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Deprecated; consider switching to `AnyReader` or use `GenericReader`
|
||||
/// to use previous API.
|
||||
pub const Reader = GenericReader;
|
||||
/// Deprecated; consider switching to `AnyWriter` or use `GenericWriter`
|
||||
/// to use previous API.
|
||||
pub const Writer = GenericWriter;
|
||||
|
||||
pub const AnyReader = @import("io/Reader.zig");
|
||||
pub const AnyWriter = @import("io/Writer.zig");
|
||||
|
||||
pub const Writer = @import("io/writer.zig").Writer;
|
||||
pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream;
|
||||
|
||||
pub const BufferedWriter = @import("io/buffered_writer.zig").BufferedWriter;
|
||||
@ -652,6 +712,7 @@ pub fn PollFiles(comptime StreamEnum: type) type {
|
||||
|
||||
test {
|
||||
_ = AnyReader;
|
||||
_ = AnyWriter;
|
||||
_ = @import("io/bit_reader.zig");
|
||||
_ = @import("io/bit_writer.zig");
|
||||
_ = @import("io/buffered_atomic_file.zig");
|
||||
@ -661,7 +722,6 @@ test {
|
||||
_ = @import("io/counting_writer.zig");
|
||||
_ = @import("io/counting_reader.zig");
|
||||
_ = @import("io/fixed_buffer_stream.zig");
|
||||
_ = @import("io/writer.zig");
|
||||
_ = @import("io/peek_stream.zig");
|
||||
_ = @import("io/seekable_stream.zig");
|
||||
_ = @import("io/stream_source.zig");
|
||||
|
60
lib/std/io/Writer.zig
Normal file
60
lib/std/io/Writer.zig
Normal file
@ -0,0 +1,60 @@
|
||||
const std = @import("../std.zig");
|
||||
const assert = std.debug.assert;
|
||||
const mem = std.mem;
|
||||
|
||||
context: *const anyopaque,
|
||||
writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize,
|
||||
|
||||
const Self = @This();
|
||||
pub const Error = anyerror;
|
||||
|
||||
pub fn write(self: Self, bytes: []const u8) anyerror!usize {
|
||||
return self.writeFn(self.context, bytes);
|
||||
}
|
||||
|
||||
pub fn writeAll(self: Self, bytes: []const u8) anyerror!void {
|
||||
var index: usize = 0;
|
||||
while (index != bytes.len) {
|
||||
index += try self.write(bytes[index..]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void {
|
||||
return std.fmt.format(self, format, args);
|
||||
}
|
||||
|
||||
pub fn writeByte(self: Self, byte: u8) anyerror!void {
|
||||
const array = [1]u8{byte};
|
||||
return self.writeAll(&array);
|
||||
}
|
||||
|
||||
pub fn writeByteNTimes(self: Self, byte: u8, n: usize) anyerror!void {
|
||||
var bytes: [256]u8 = undefined;
|
||||
@memset(bytes[0..], byte);
|
||||
|
||||
var remaining: usize = n;
|
||||
while (remaining > 0) {
|
||||
const to_write = @min(remaining, bytes.len);
|
||||
try self.writeAll(bytes[0..to_write]);
|
||||
remaining -= to_write;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) anyerror!void {
|
||||
var i: usize = 0;
|
||||
while (i < n) : (i += 1) {
|
||||
try self.writeAll(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) anyerror!void {
|
||||
var bytes: [@divExact(@typeInfo(T).Int.bits, 8)]u8 = undefined;
|
||||
mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
|
||||
return self.writeAll(&bytes);
|
||||
}
|
||||
|
||||
pub fn writeStruct(self: Self, value: anytype) anyerror!void {
|
||||
// Only extern and packed structs have defined in-memory layout.
|
||||
comptime assert(@typeInfo(@TypeOf(value)).Struct.layout != .Auto);
|
||||
return self.writeAll(mem.asBytes(&value));
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
const std = @import("../std.zig");
|
||||
const assert = std.debug.assert;
|
||||
const mem = std.mem;
|
||||
|
||||
pub fn Writer(
|
||||
comptime Context: type,
|
||||
comptime WriteError: type,
|
||||
comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize,
|
||||
) type {
|
||||
return struct {
|
||||
context: Context,
|
||||
|
||||
const Self = @This();
|
||||
pub const Error = WriteError;
|
||||
|
||||
pub fn write(self: Self, bytes: []const u8) Error!usize {
|
||||
return writeFn(self.context, bytes);
|
||||
}
|
||||
|
||||
pub fn writeAll(self: Self, bytes: []const u8) Error!void {
|
||||
var index: usize = 0;
|
||||
while (index != bytes.len) {
|
||||
index += try self.write(bytes[index..]);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn print(self: Self, comptime format: []const u8, args: anytype) Error!void {
|
||||
return std.fmt.format(self, format, args);
|
||||
}
|
||||
|
||||
pub fn writeByte(self: Self, byte: u8) Error!void {
|
||||
const array = [1]u8{byte};
|
||||
return self.writeAll(&array);
|
||||
}
|
||||
|
||||
pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void {
|
||||
var bytes: [256]u8 = undefined;
|
||||
@memset(bytes[0..], byte);
|
||||
|
||||
var remaining: usize = n;
|
||||
while (remaining > 0) {
|
||||
const to_write = @min(remaining, bytes.len);
|
||||
try self.writeAll(bytes[0..to_write]);
|
||||
remaining -= to_write;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) Error!void {
|
||||
var i: usize = 0;
|
||||
while (i < n) : (i += 1) {
|
||||
try self.writeAll(bytes);
|
||||
}
|
||||
}
|
||||
|
||||
pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) Error!void {
|
||||
var bytes: [@divExact(@typeInfo(T).Int.bits, 8)]u8 = undefined;
|
||||
mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian);
|
||||
return self.writeAll(&bytes);
|
||||
}
|
||||
|
||||
pub fn writeStruct(self: Self, value: anytype) Error!void {
|
||||
// Only extern and packed structs have defined in-memory layout.
|
||||
comptime assert(@typeInfo(@TypeOf(value)).Struct.layout != .Auto);
|
||||
return self.writeAll(mem.asBytes(&value));
|
||||
}
|
||||
};
|
||||
}
|
Loading…
Reference in New Issue
Block a user