aboutsummaryrefslogtreecommitdiff
path: root/lib/std/fmt.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2020-02-14 10:27:44 -0500
committerAndrew Kelley <andrew@ziglang.org>2020-02-14 10:27:44 -0500
commita8b36fbe34e4acfea1fcb348fbed321b05611fd3 (patch)
tree23f489f85c427a003577f5c40b74201ba8c85ddb /lib/std/fmt.zig
parentcdc5070f216a924d24588b8d0fe06400e036e6bf (diff)
parent40b9db7cad6f876bb3e8fa32d7b32bbd4bc983ea (diff)
downloadzig-a8b36fbe34e4acfea1fcb348fbed321b05611fd3.tar.gz
zig-a8b36fbe34e4acfea1fcb348fbed321b05611fd3.zip
Merge remote-tracking branch 'origin/master' into llvm10
Diffstat (limited to 'lib/std/fmt.zig')
-rw-r--r--lib/std/fmt.zig56
1 files changed, 50 insertions, 6 deletions
diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig
index 370717a4f7..a0ec668769 100644
--- a/lib/std/fmt.zig
+++ b/lib/std/fmt.zig
@@ -69,12 +69,12 @@ fn peekIsAlign(comptime fmt: []const u8) bool {
///
/// If a formatted user type contains a function of the type
/// ```
-/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void
+/// fn format(value: ?, comptime fmt: []const u8, options: std.fmt.FormatOptions, context: var, comptime Errors: type, comptime output: fn (@TypeOf(context), []const u8) Errors!void) Errors!void
/// ```
/// with `?` being the type formatted, this function will be called instead of the default implementation.
/// This allows user types to be formatted in a logical manner instead of dumping all fields of the type.
///
-/// A user type may be a `struct`, `union` or `enum` type.
+/// A user type may be a `struct`, `vector`, `union` or `enum` type.
pub fn format(
context: var,
comptime Errors: type,
@@ -373,11 +373,11 @@ pub fn formatType(
try output(context, @typeName(T));
if (enumInfo.is_exhaustive) {
try output(context, ".");
- return formatType(@tagName(value), "", options, context, Errors, output, max_depth);
+ try output(context, @tagName(value));
} else {
// TODO: when @tagName works on exhaustive enums print known enum strings
try output(context, "(");
- try formatType(@enumToInt(value), "", options, context, Errors, output, max_depth);
+ try formatType(@enumToInt(value), fmt, options, context, Errors, output, max_depth);
try output(context, ")");
}
},
@@ -397,7 +397,7 @@ pub fn formatType(
try output(context, " = ");
inline for (info.fields) |u_field| {
if (@enumToInt(@as(UnionTagType, value)) == u_field.enum_field.?.value) {
- try formatType(@field(value, u_field.name), "", options, context, Errors, output, max_depth - 1);
+ try formatType(@field(value, u_field.name), fmt, options, context, Errors, output, max_depth - 1);
}
}
try output(context, " }");
@@ -424,7 +424,7 @@ pub fn formatType(
}
try output(context, @memberName(T, field_i));
try output(context, " = ");
- try formatType(@field(value, @memberName(T, field_i)), "", options, context, Errors, output, max_depth - 1);
+ try formatType(@field(value, @memberName(T, field_i)), fmt, options, context, Errors, output, max_depth - 1);
}
try output(context, " }");
},
@@ -474,6 +474,18 @@ pub fn formatType(
});
return formatType(@as(Slice, &value), fmt, options, context, Errors, output, max_depth);
},
+ .Vector => {
+ const len = @typeInfo(T).Vector.len;
+ try output(context, "{ ");
+ var i: usize = 0;
+ while (i < len) : (i += 1) {
+ try formatValue(value[i], fmt, options, context, Errors, output);
+ if (i < len - 1) {
+ try output(context, ", ");
+ }
+ }
+ try output(context, " }");
+ },
.Fn => {
return format(context, Errors, output, "{}@{x}", .{ @typeName(T), @ptrToInt(value) });
},
@@ -500,6 +512,7 @@ fn formatValue(
switch (@typeId(T)) {
.Float => return formatFloatValue(value, fmt, options, context, Errors, output),
.Int, .ComptimeInt => return formatIntValue(value, fmt, options, context, Errors, output),
+ .Bool => return output(context, if (value) "true" else "false"),
else => comptime unreachable,
}
}
@@ -1343,6 +1356,20 @@ test "enum" {
try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value});
}
+test "non-exhaustive enum" {
+ const Enum = enum(u16) {
+ One = 0x000f,
+ Two = 0xbeef,
+ _,
+ };
+ try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One});
+ try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two});
+ try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)});
+ try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One});
+ try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two});
+ try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)});
+}
+
test "float.scientific" {
try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)});
try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)});
@@ -1699,3 +1726,20 @@ test "positional with specifier" {
test "positional/alignment/width/precision" {
try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)});
}
+
+test "vector" {
+ // https://github.com/ziglang/zig/issues/3317
+ if (builtin.arch == .mipsel) return error.SkipZigTest;
+
+ const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false };
+ const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 };
+ const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 };
+
+ try testFmt("{ true, false, true, false }", "{}", .{vbool});
+ try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64});
+ try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64});
+ try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64});
+ try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64});
+ try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64});
+ try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64});
+}