From 84323504acc2c872a55d0b59ff2c54b60b809405 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Wed, 5 Feb 2020 16:52:18 -0500 Subject: [PATCH] std.fmt.format: comptime output parameter --- lib/std/fmt.zig | 32 +++++++++++++++--------------- lib/std/io/out_stream.zig | 2 +- lib/std/net.zig | 16 ++++++++++----- src-self-hosted/dep_tokenizer.zig | 33 ++++++++++--------------------- 4 files changed, 38 insertions(+), 45 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index e0d58a23e6..370717a4f7 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -78,7 +78,7 @@ fn peekIsAlign(comptime fmt: []const u8) bool { pub fn format( context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, comptime fmt: []const u8, args: var, ) Errors!void { @@ -326,7 +326,7 @@ pub fn formatType( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, max_depth: usize, ) Errors!void { if (comptime std.mem.eql(u8, fmt, "*")) { @@ -488,7 +488,7 @@ fn formatValue( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { if (comptime std.mem.eql(u8, fmt, "B")) { return formatBytes(value, options, 1000, context, Errors, output); @@ -510,7 +510,7 @@ pub fn formatIntValue( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { comptime var radix = 10; comptime var uppercase = false; @@ -552,7 +552,7 @@ fn formatFloatValue( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "e")) { return formatFloatScientific(value, options, context, Errors, output); @@ -569,7 +569,7 @@ pub fn formatText( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { if (fmt.len == 0) { return output(context, bytes); @@ -590,7 +590,7 @@ pub fn formatAsciiChar( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { return output(context, @as(*const [1]u8, &c)[0..]); } @@ -600,7 +600,7 @@ pub fn formatBuf( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { try output(context, buf); @@ -620,7 +620,7 @@ pub fn formatFloatScientific( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { var x = @floatCast(f64, value); @@ -715,7 +715,7 @@ pub fn formatFloatDecimal( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { var x = @as(f64, value); @@ -861,7 +861,7 @@ pub fn formatBytes( comptime radix: usize, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { if (value == 0) { return output(context, "0B"); @@ -902,7 +902,7 @@ pub fn formatInt( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { const int_value = if (@TypeOf(value) == comptime_int) blk: { const Int = math.IntFittingRange(value, value); @@ -924,7 +924,7 @@ fn formatIntSigned( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { const new_options = FormatOptions{ .width = if (options.width) |w| (if (w == 0) 0 else w - 1) else null, @@ -955,7 +955,7 @@ fn formatIntUnsigned( options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { assert(base >= 2); var buf: [math.max(@TypeOf(value).bit_count, 1)]u8 = undefined; @@ -1419,7 +1419,7 @@ test "custom" { options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) { return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y }); @@ -1626,7 +1626,7 @@ test "formatType max_depth" { options: FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) Errors!void { if (fmt.len == 0) { return std.fmt.format(context, Errors, output, "({d:.3},{d:.3})", .{ self.x, self.y }); diff --git a/lib/std/io/out_stream.zig b/lib/std/io/out_stream.zig index 265be066a1..56d3324e6f 100644 --- a/lib/std/io/out_stream.zig +++ b/lib/std/io/out_stream.zig @@ -36,7 +36,7 @@ pub fn OutStream(comptime WriteError: type) type { } pub fn print(self: *Self, comptime format: []const u8, args: var) Error!void { - return std.fmt.format(self, Error, self.writeFn, format, args); + return std.fmt.format(self, Error, write, format, args); } pub fn writeByte(self: *Self, byte: u8) Error!void { diff --git a/lib/std/net.zig b/lib/std/net.zig index c113462855..2fce17409b 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -271,7 +271,7 @@ pub const Address = extern union { options: std.fmt.FormatOptions, context: var, comptime Errors: type, - output: fn (@TypeOf(context), []const u8) Errors!void, + comptime output: fn (@TypeOf(context), []const u8) Errors!void, ) !void { switch (self.any.family) { os.AF_INET => { @@ -361,7 +361,7 @@ pub const Address = extern union { }; pub fn connectUnixSocket(path: []const u8) !fs.File { - const opt_non_block = if (std.io.mode == .evented) os.SOCK_NONBLOCK else 0; + const opt_non_block = if (std.io.is_async) os.SOCK_NONBLOCK else 0; const sockfd = try os.socket( os.AF_UNIX, os.SOCK_STREAM | os.SOCK_CLOEXEC | opt_non_block, @@ -377,7 +377,10 @@ pub fn connectUnixSocket(path: []const u8) !fs.File { addr.getOsSockLen(), ); - return fs.File.openHandle(sockfd); + return fs.File{ + .handle = socket, + .is_blocking = std.io.mode, + }; } pub const AddressList = struct { @@ -412,7 +415,7 @@ pub fn tcpConnectToAddress(address: Address) !fs.File { errdefer os.close(sockfd); try os.connect(sockfd, &address.any, address.getOsSockLen()); - return fs.File{ .handle = sockfd }; + return fs.File{ .handle = sockfd, .io_mode = std.io.mode }; } /// Call `AddressList.deinit` on the result. @@ -1379,7 +1382,10 @@ pub const StreamServer = struct { var adr_len: os.socklen_t = @sizeOf(Address); if (os.accept4(self.sockfd.?, &accepted_addr.any, &adr_len, accept_flags)) |fd| { return Connection{ - .file = fs.File.openHandle(fd), + .file = fs.File{ + .handle = fd, + .io_mode = std.io.mode, + }, .address = accepted_addr, }; } else |err| switch (err) { diff --git a/src-self-hosted/dep_tokenizer.zig b/src-self-hosted/dep_tokenizer.zig index 9a13faa5f2..5c250cdb99 100644 --- a/src-self-hosted/dep_tokenizer.zig +++ b/src-self-hosted/dep_tokenizer.zig @@ -998,7 +998,8 @@ fn printCharValues(out: var, bytes: []const u8) !void { fn printUnderstandableChar(out: var, char: u8) !void { if (!std.ascii.isPrint(char) or char == ' ') { - std.fmt.format(out.context, anyerror, out.output, "\\x{X:2}", .{char}) catch {}; + const output = @typeInfo(@TypeOf(out)).Pointer.child.output; + std.fmt.format(out.context, anyerror, output, "\\x{X:2}", .{char}) catch {}; } else { try out.write("'"); try out.write(&[_]u8{printable_char_tab[char]}); @@ -1021,34 +1022,20 @@ comptime { // output: must be a function that takes a `self` idiom parameter // and a bytes parameter // context: must be that self -fn makeOutput(output: var, context: var) Output(@TypeOf(output)) { - return Output(@TypeOf(output)){ - .output = output, +fn makeOutput(comptime output: var, context: var) Output(output, @TypeOf(context)) { + return Output(output, @TypeOf(context)){ .context = context, }; } -fn Output(comptime T: type) type { - const args = switch (@typeInfo(T)) { - .Fn => |f| f.args, - else => @compileError("output parameter is not a function"), - }; - if (args.len != 2) { - @compileError("output function must take 2 arguments"); - } - const at0 = args[0].arg_type orelse @compileError("output arg[0] does not have a type"); - const at1 = args[1].arg_type orelse @compileError("output arg[1] does not have a type"); - const arg1p = switch (@typeInfo(at1)) { - .Pointer => |p| p, - else => @compileError("output arg[1] is not a slice"), - }; - if (arg1p.child != u8) @compileError("output arg[1] is not a u8 slice"); +fn Output(comptime output_func: var, comptime Context: type) type { return struct { - output: T, - context: at0, + context: Context, - fn write(self: *@This(), bytes: []const u8) !void { - try self.output(self.context, bytes); + pub const output = output_func; + + fn write(self: @This(), bytes: []const u8) !void { + try output_func(self.context, bytes); } }; }