| author | |
| committer | |
| log | e392c1a0b33e69156c36234e6584be306caf16ef |
| tree | 752d92804098a096553dcaa1112634db93033a27 |
| parent | 4dfca01de4fda9a195048011b3339686dce4e936 |
This is a companion to #17344 to apply the same change to the
`std.io.Writer` interface.4 files changed, 123 insertions(+), 70 deletions(-)
CMakeLists.txt+1-1| ... | @@ -265,7 +265,7 @@ set(ZIG_STAGE2_SOURCES | ... | @@ -265,7 +265,7 @@ set(ZIG_STAGE2_SOURCES |
| 265 | "${CMAKE_SOURCE_DIR}/lib/std/io/limited_reader.zig" | 265 | "${CMAKE_SOURCE_DIR}/lib/std/io/limited_reader.zig" |
| 266 | "${CMAKE_SOURCE_DIR}/lib/std/io/Reader.zig" | 266 | "${CMAKE_SOURCE_DIR}/lib/std/io/Reader.zig" |
| 267 | "${CMAKE_SOURCE_DIR}/lib/std/io/seekable_stream.zig" | 267 | "${CMAKE_SOURCE_DIR}/lib/std/io/seekable_stream.zig" |
| 268 | "${CMAKE_SOURCE_DIR}/lib/std/io/writer.zig" | 268 | "${CMAKE_SOURCE_DIR}/lib/std/io/Writer.zig" |
| 269 | "${CMAKE_SOURCE_DIR}/lib/std/json.zig" | 269 | "${CMAKE_SOURCE_DIR}/lib/std/json.zig" |
| 270 | "${CMAKE_SOURCE_DIR}/lib/std/json/stringify.zig" | 270 | "${CMAKE_SOURCE_DIR}/lib/std/json/stringify.zig" |
| 271 | "${CMAKE_SOURCE_DIR}/lib/std/leb128.zig" | 271 | "${CMAKE_SOURCE_DIR}/lib/std/leb128.zig" |
lib/std/io.zig+62-2| ... | @@ -333,13 +333,73 @@ pub fn GenericReader( | ... | @@ -333,13 +333,73 @@ pub fn GenericReader( |
| 333 | }; | 333 | }; |
| 334 | } | 334 | } |
| 335 | 335 | ||
| 336 | pub fn GenericWriter( | ||
| 337 | comptime Context: type, | ||
| 338 | comptime WriteError: type, | ||
| 339 | comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize, | ||
| 340 | ) type { | ||
| 341 | return struct { | ||
| 342 | context: Context, | ||
| 343 | |||
| 344 | const Self = @This(); | ||
| 345 | pub const Error = WriteError; | ||
| 346 | |||
| 347 | pub inline fn write(self: Self, bytes: []const u8) Error!usize { | ||
| 348 | return writeFn(self.context, bytes); | ||
| 349 | } | ||
| 350 | |||
| 351 | pub inline fn writeAll(self: Self, bytes: []const u8) Error!void { | ||
| 352 | return @errorCast(self.any().writeAll(bytes)); | ||
| 353 | } | ||
| 354 | |||
| 355 | pub inline fn print(self: Self, comptime format: []const u8, args: anytype) Error!void { | ||
| 356 | return @errorCast(self.any().print(format, args)); | ||
| 357 | } | ||
| 358 | |||
| 359 | pub inline fn writeByte(self: Self, byte: u8) Error!void { | ||
| 360 | return @errorCast(self.any().writeByte(byte)); | ||
| 361 | } | ||
| 362 | |||
| 363 | pub inline fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void { | ||
| 364 | return @errorCast(self.any().writeByteNTimes(byte, n)); | ||
| 365 | } | ||
| 366 | |||
| 367 | pub inline fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) Error!void { | ||
| 368 | return @errorCast(self.any().writeBytesNTimes(bytes, n)); | ||
| 369 | } | ||
| 370 | |||
| 371 | pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { | ||
| 372 | return @errorCast(self.any().writeInt(T, value, endian)); | ||
| 373 | } | ||
| 374 | |||
| 375 | pub inline fn writeStruct(self: Self, value: anytype) Error!void { | ||
| 376 | return @errorCast(self.any().writeStruct(value)); | ||
| 377 | } | ||
| 378 | |||
| 379 | pub inline fn any(self: *const Self) AnyWriter { | ||
| 380 | return .{ | ||
| 381 | .context = @ptrCast(&self.context), | ||
| 382 | .writeFn = typeErasedWriteFn, | ||
| 383 | }; | ||
| 384 | } | ||
| 385 | |||
| 386 | fn typeErasedWriteFn(context: *const anyopaque, bytes: []const u8) anyerror!usize { | ||
| 387 | const ptr: *const Context = @alignCast(@ptrCast(context)); | ||
| 388 | return writeFn(ptr.*, bytes); | ||
| 389 | } | ||
| 390 | }; | ||
| 391 | } | ||
| 392 | |||
| 336 | /// Deprecated; consider switching to `AnyReader` or use `GenericReader` | 393 | /// Deprecated; consider switching to `AnyReader` or use `GenericReader` |
| 337 | /// to use previous API. | 394 | /// to use previous API. |
| 338 | pub const Reader = GenericReader; | 395 | pub const Reader = GenericReader; |
| 396 | /// Deprecated; consider switching to `AnyWriter` or use `GenericWriter` | ||
| 397 | /// to use previous API. | ||
| 398 | pub const Writer = GenericWriter; | ||
| 339 | 399 | ||
| 340 | pub const AnyReader = @import("io/Reader.zig"); | 400 | pub const AnyReader = @import("io/Reader.zig"); |
| 401 | pub const AnyWriter = @import("io/Writer.zig"); | ||
| 341 | 402 | ||
| 342 | pub const Writer = @import("io/writer.zig").Writer; | ||
| 343 | pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; | 403 | pub const SeekableStream = @import("io/seekable_stream.zig").SeekableStream; |
| 344 | 404 | ||
| 345 | pub const BufferedWriter = @import("io/buffered_writer.zig").BufferedWriter; | 405 | pub const BufferedWriter = @import("io/buffered_writer.zig").BufferedWriter; |
| ... | @@ -652,6 +712,7 @@ pub fn PollFiles(comptime StreamEnum: type) type { | ... | @@ -652,6 +712,7 @@ pub fn PollFiles(comptime StreamEnum: type) type { |
| 652 | 712 | ||
| 653 | test { | 713 | test { |
| 654 | _ = AnyReader; | 714 | _ = AnyReader; |
| 715 | _ = AnyWriter; | ||
| 655 | _ = @import("io/bit_reader.zig"); | 716 | _ = @import("io/bit_reader.zig"); |
| 656 | _ = @import("io/bit_writer.zig"); | 717 | _ = @import("io/bit_writer.zig"); |
| 657 | _ = @import("io/buffered_atomic_file.zig"); | 718 | _ = @import("io/buffered_atomic_file.zig"); |
| ... | @@ -661,7 +722,6 @@ test { | ... | @@ -661,7 +722,6 @@ test { |
| 661 | _ = @import("io/counting_writer.zig"); | 722 | _ = @import("io/counting_writer.zig"); |
| 662 | _ = @import("io/counting_reader.zig"); | 723 | _ = @import("io/counting_reader.zig"); |
| 663 | _ = @import("io/fixed_buffer_stream.zig"); | 724 | _ = @import("io/fixed_buffer_stream.zig"); |
| 664 | _ = @import("io/writer.zig"); | ||
| 665 | _ = @import("io/peek_stream.zig"); | 725 | _ = @import("io/peek_stream.zig"); |
| 666 | _ = @import("io/seekable_stream.zig"); | 726 | _ = @import("io/seekable_stream.zig"); |
| 667 | _ = @import("io/stream_source.zig"); | 727 | _ = @import("io/stream_source.zig"); |
lib/std/io/Writer.zig created+60| ... | @@ -0,0 +1,60 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | context: *const anyopaque, | ||
| 6 | writeFn: *const fn (context: *const anyopaque, bytes: []const u8) anyerror!usize, | ||
| 7 | |||
| 8 | const Self = @This(); | ||
| 9 | pub const Error = anyerror; | ||
| 10 | |||
| 11 | pub fn write(self: Self, bytes: []const u8) anyerror!usize { | ||
| 12 | return self.writeFn(self.context, bytes); | ||
| 13 | } | ||
| 14 | |||
| 15 | pub fn writeAll(self: Self, bytes: []const u8) anyerror!void { | ||
| 16 | var index: usize = 0; | ||
| 17 | while (index != bytes.len) { | ||
| 18 | index += try self.write(bytes[index..]); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | |||
| 22 | pub fn print(self: Self, comptime format: []const u8, args: anytype) anyerror!void { | ||
| 23 | return std.fmt.format(self, format, args); | ||
| 24 | } | ||
| 25 | |||
| 26 | pub fn writeByte(self: Self, byte: u8) anyerror!void { | ||
| 27 | const array = [1]u8{byte}; | ||
| 28 | return self.writeAll(&array); | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn writeByteNTimes(self: Self, byte: u8, n: usize) anyerror!void { | ||
| 32 | var bytes: [256]u8 = undefined; | ||
| 33 | @memset(bytes[0..], byte); | ||
| 34 | |||
| 35 | var remaining: usize = n; | ||
| 36 | while (remaining > 0) { | ||
| 37 | const to_write = @min(remaining, bytes.len); | ||
| 38 | try self.writeAll(bytes[0..to_write]); | ||
| 39 | remaining -= to_write; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) anyerror!void { | ||
| 44 | var i: usize = 0; | ||
| 45 | while (i < n) : (i += 1) { | ||
| 46 | try self.writeAll(bytes); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) anyerror!void { | ||
| 51 | var bytes: [@divExact(@typeInfo(T).Int.bits, 8)]u8 = undefined; | ||
| 52 | mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); | ||
| 53 | return self.writeAll(&bytes); | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn writeStruct(self: Self, value: anytype) anyerror!void { | ||
| 57 | // Only extern and packed structs have defined in-memory layout. | ||
| 58 | comptime assert(@typeInfo(@TypeOf(value)).Struct.layout != .Auto); | ||
| 59 | return self.writeAll(mem.asBytes(&value)); | ||
| 60 | } | ||
lib/std/io/writer.zig deleted-67| ... | @@ -1,67 +0,0 @@ | ||
| 1 | const std = @import("../std.zig"); | ||
| 2 | const assert = std.debug.assert; | ||
| 3 | const mem = std.mem; | ||
| 4 | |||
| 5 | pub fn Writer( | ||
| 6 | comptime Context: type, | ||
| 7 | comptime WriteError: type, | ||
| 8 | comptime writeFn: fn (context: Context, bytes: []const u8) WriteError!usize, | ||
| 9 | ) type { | ||
| 10 | return struct { | ||
| 11 | context: Context, | ||
| 12 | |||
| 13 | const Self = @This(); | ||
| 14 | pub const Error = WriteError; | ||
| 15 | |||
| 16 | pub fn write(self: Self, bytes: []const u8) Error!usize { | ||
| 17 | return writeFn(self.context, bytes); | ||
| 18 | } | ||
| 19 | |||
| 20 | pub fn writeAll(self: Self, bytes: []const u8) Error!void { | ||
| 21 | var index: usize = 0; | ||
| 22 | while (index != bytes.len) { | ||
| 23 | index += try self.write(bytes[index..]); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | |||
| 27 | pub fn print(self: Self, comptime format: []const u8, args: anytype) Error!void { | ||
| 28 | return std.fmt.format(self, format, args); | ||
| 29 | } | ||
| 30 | |||
| 31 | pub fn writeByte(self: Self, byte: u8) Error!void { | ||
| 32 | const array = [1]u8{byte}; | ||
| 33 | return self.writeAll(&array); | ||
| 34 | } | ||
| 35 | |||
| 36 | pub fn writeByteNTimes(self: Self, byte: u8, n: usize) Error!void { | ||
| 37 | var bytes: [256]u8 = undefined; | ||
| 38 | @memset(bytes[0..], byte); | ||
| 39 | |||
| 40 | var remaining: usize = n; | ||
| 41 | while (remaining > 0) { | ||
| 42 | const to_write = @min(remaining, bytes.len); | ||
| 43 | try self.writeAll(bytes[0..to_write]); | ||
| 44 | remaining -= to_write; | ||
| 45 | } | ||
| 46 | } | ||
| 47 | |||
| 48 | pub fn writeBytesNTimes(self: Self, bytes: []const u8, n: usize) Error!void { | ||
| 49 | var i: usize = 0; | ||
| 50 | while (i < n) : (i += 1) { | ||
| 51 | try self.writeAll(bytes); | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | pub inline fn writeInt(self: Self, comptime T: type, value: T, endian: std.builtin.Endian) Error!void { | ||
| 56 | var bytes: [@divExact(@typeInfo(T).Int.bits, 8)]u8 = undefined; | ||
| 57 | mem.writeInt(std.math.ByteAlignedInt(@TypeOf(value)), &bytes, value, endian); | ||
| 58 | return self.writeAll(&bytes); | ||
| 59 | } | ||
| 60 | |||
| 61 | pub fn writeStruct(self: Self, value: anytype) Error!void { | ||
| 62 | // Only extern and packed structs have defined in-memory layout. | ||
| 63 | comptime assert(@typeInfo(@TypeOf(value)).Struct.layout != .Auto); | ||
| 64 | return self.writeAll(mem.asBytes(&value)); | ||
| 65 | } | ||
| 66 | }; | ||
| 67 | } | ||