Commit 84323504ac

Andrew Kelley <andrew@ziglang.org>
2020-02-05 22:52:18
std.fmt.format: comptime output parameter
1 parent 378d733
Changed files (4)
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 {
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 });
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) {
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,
+
+        pub const output = output_func;
 
-        fn write(self: *@This(), bytes: []const u8) !void {
-            try self.output(self.context, bytes);
+        fn write(self: @This(), bytes: []const u8) !void {
+            try output_func(self.context, bytes);
         }
     };
 }