Commit e1e9ff9546
Changed files (1)
lib
lib/std/fmtstream.zig
@@ -972,20 +972,9 @@ fn formatIntUnsigned(
}
pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize {
- var context = FormatIntBuf{
- .out_buf = out_buf,
- .index = 0,
- };
- formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable;
- return context.index;
-}
-const FormatIntBuf = struct {
- out_buf: []u8,
- index: usize,
-};
-fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) {
- mem.copy(u8, context.out_buf[context.index..], bytes);
- context.index += bytes.len;
+ var fbs = std.io.fixedBufferStream(out_buf);
+ formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable;
+ return fbs.pos;
}
pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T {
@@ -1085,48 +1074,48 @@ fn digitToChar(digit: u8, uppercase: bool) u8 {
};
}
-const BufPrintContext = struct {
- remaining: []u8,
-};
-
-fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
- if (context.remaining.len < bytes.len) {
- mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
- return error.BufferTooSmall;
- }
- mem.copy(u8, context.remaining, bytes);
- context.remaining = context.remaining[bytes.len..];
-}
-
-pub const BufPrintError = error{
- /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
- BufferTooSmall,
-};
-pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
- var context = BufPrintContext{ .remaining = buf };
- try format(&context, BufPrintError, bufPrintWrite, fmt, args);
- return buf[0 .. buf.len - context.remaining.len];
-}
-
-pub const AllocPrintError = error{OutOfMemory};
-
-pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
- var size: usize = 0;
- format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
- const buf = try allocator.alloc(u8, size);
- return bufPrint(buf, fmt, args) catch |err| switch (err) {
- error.BufferTooSmall => unreachable, // we just counted the size above
- };
-}
-
-fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
- size.* += bytes.len;
-}
-
-pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
- const result = try allocPrint(allocator, fmt ++ "\x00", args);
- return result[0 .. result.len - 1 :0];
-}
+// const BufPrintContext = struct {
+// remaining: []u8,
+// };
+
+// fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void {
+// if (context.remaining.len < bytes.len) {
+// mem.copy(u8, context.remaining, bytes[0..context.remaining.len]);
+// return error.BufferTooSmall;
+// }
+// mem.copy(u8, context.remaining, bytes);
+// context.remaining = context.remaining[bytes.len..];
+// }
+
+// pub const BufPrintError = error{
+// /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes.
+// BufferTooSmall,
+// };
+// pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 {
+// var context = BufPrintContext{ .remaining = buf };
+// try format(&context, BufPrintError, bufPrintWrite, fmt, args);
+// return buf[0 .. buf.len - context.remaining.len];
+// }
+
+// pub const AllocPrintError = error{OutOfMemory};
+
+// pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 {
+// var size: usize = 0;
+// format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {};
+// const buf = try allocator.alloc(u8, size);
+// return bufPrint(buf, fmt, args) catch |err| switch (err) {
+// error.BufferTooSmall => unreachable, // we just counted the size above
+// };
+// }
+
+// fn countSize(size: *usize, bytes: []const u8) (error{}!void) {
+// size.* += bytes.len;
+// }
+
+// pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 {
+// const result = try allocPrint(allocator, fmt ++ "\x00", args);
+// return result[0 .. result.len - 1 :0];
+// }
test "bufPrintInt" {
var buffer: [100]u8 = undefined;
@@ -1153,566 +1142,566 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options:
return buf[0..formatIntBuf(buf, value, base, uppercase, options)];
}
-test "parse u64 digit too big" {
- _ = parseUnsigned(u64, "123a", 10) catch |err| {
- if (err == error.InvalidCharacter) return;
- unreachable;
- };
- unreachable;
-}
-
-test "parse unsigned comptime" {
- comptime {
- std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
- }
-}
-
-test "optional" {
- {
- const value: ?i32 = 1234;
- try testFmt("optional: 1234\n", "optional: {}\n", .{value});
- }
- {
- const value: ?i32 = null;
- try testFmt("optional: null\n", "optional: {}\n", .{value});
- }
-}
-
-test "error" {
- {
- const value: anyerror!i32 = 1234;
- try testFmt("error union: 1234\n", "error union: {}\n", .{value});
- }
- {
- const value: anyerror!i32 = error.InvalidChar;
- try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
- }
-}
-
-test "int.small" {
- {
- const value: u3 = 0b101;
- try testFmt("u3: 5\n", "u3: {}\n", .{value});
- }
-}
-
-test "int.specifier" {
- {
- const value: u8 = 'a';
- try testFmt("u8: a\n", "u8: {c}\n", .{value});
- }
- {
- const value: u8 = 0b1100;
- try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
- }
-}
-
-test "int.padded" {
- try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
- try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
-}
-
-test "buffer" {
- {
- var buf1: [32]u8 = undefined;
- var context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- var res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "1234"));
-
- context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "a"));
-
- context = BufPrintContext{ .remaining = buf1[0..] };
- try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
- res = buf1[0 .. buf1.len - context.remaining.len];
- std.testing.expect(mem.eql(u8, res, "1100"));
- }
-}
-
-test "array" {
- {
- const value: [3]u8 = "abc".*;
- try testFmt("array: abc\n", "array: {}\n", .{value});
- try testFmt("array: abc\n", "array: {}\n", .{&value});
-
- var buf: [100]u8 = undefined;
- try testFmt(
- try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
- "array: {*}\n",
- .{&value},
- );
- }
-}
-
-test "slice" {
- {
- const value: []const u8 = "abc";
- try testFmt("slice: abc\n", "slice: {}\n", .{value});
- }
- {
- const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
- try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
- }
-
- try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
- try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
-}
-
-test "pointer" {
- {
- const value = @intToPtr(*align(1) i32, 0xdeadbeef);
- try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
- try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
- }
- {
- const value = @intToPtr(fn () void, 0xdeadbeef);
- try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
- }
- {
- const value = @intToPtr(fn () void, 0xdeadbeef);
- try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
- }
-}
-
-test "cstr" {
- try testFmt(
- "cstr: Test C\n",
- "cstr: {s}\n",
- .{@ptrCast([*c]const u8, "Test C")},
- );
- try testFmt(
- "cstr: Test C \n",
- "cstr: {s:10}\n",
- .{@ptrCast([*c]const u8, "Test C")},
- );
-}
-
-test "filesize" {
- try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
- try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
-}
-
-test "struct" {
- {
- const Struct = struct {
- field: u8,
- };
- const value = Struct{ .field = 42 };
- try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
- try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
- }
- {
- const Struct = struct {
- a: u0,
- b: u1,
- };
- const value = Struct{ .a = 0, .b = 1 };
- try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
- }
-}
-
-test "enum" {
- const Enum = enum {
- One,
- Two,
- };
- const value = Enum.Two;
- try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
- 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)});
- try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
- try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
-}
-
-test "float.scientific.precision" {
- try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
- try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
- try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
- // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
- // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
- try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
-}
-
-test "float.special" {
- try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
- // negative nan is not defined by IEE 754,
- // and ARM thus normalizes it to positive nan
- if (builtin.arch != builtin.Arch.arm) {
- try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
- }
- try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
- try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
-}
-
-test "float.decimal" {
- try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
- try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
- try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
- try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
- // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
- // -11.12339... is rounded back up to -11.1234
- try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
- try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
- try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
- try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
- try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
- try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
- try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
- try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
-}
-
-test "float.libc.sanity" {
- try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
- try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
- try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
- try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
- try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
-
- // libc differences
- //
- // This is 0.015625 exactly according to gdb. We thus round down,
- // however glibc rounds up for some reason. This occurs for all
- // floats of the form x.yyyy25 on a precision point.
- try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
- // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
- // also rounds to 630 so I'm inclined to believe libc is not
- // optimal here.
- try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
-}
-
-test "custom" {
- const Vec2 = struct {
- const SelfType = @This();
- x: f32,
- y: f32,
-
- pub fn format(
- self: SelfType,
- comptime fmt: []const u8,
- options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) !void,
- ) !void {
- if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
- return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
- } else if (comptime std.mem.eql(u8, fmt, "d")) {
- return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
- } else {
- @compileError("Unknown format character: '" ++ fmt ++ "'");
- }
- }
- };
-
- var buf1: [32]u8 = undefined;
- var value = Vec2{
- .x = 10.2,
- .y = 2.22,
- };
- try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
- try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
-
- // same thing but not passing a pointer
- try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
- try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
-}
-
-test "struct" {
- const S = struct {
- a: u32,
- b: anyerror,
- };
-
- const inst = S{
- .a = 456,
- .b = error.Unused,
- };
-
- try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
-}
-
-test "union" {
- const TU = union(enum) {
- float: f32,
- int: u32,
- };
-
- const UU = union {
- float: f32,
- int: u32,
- };
-
- const EU = extern union {
- float: f32,
- int: u32,
- };
-
- const tu_inst = TU{ .int = 123 };
- const uu_inst = UU{ .int = 456 };
- const eu_inst = EU{ .float = 321.123 };
-
- try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
-
- var buf: [100]u8 = undefined;
- const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
- std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
-
- const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
- std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
-}
-
-test "enum" {
- const E = enum {
- One,
- Two,
- Three,
- };
-
- const inst = E.Two;
-
- try testFmt("E.Two", "{}", .{inst});
-}
-
-test "struct.self-referential" {
- const S = struct {
- const SelfType = @This();
- a: ?*SelfType,
- };
-
- var inst = S{
- .a = null,
- };
- inst.a = &inst;
-
- try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
-}
-
-test "struct.zero-size" {
- const A = struct {
- fn foo() void {}
- };
- const B = struct {
- a: A,
- c: i32,
- };
-
- const a = A{};
- const b = B{ .a = a, .c = 0 };
-
- try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
-}
-
-test "bytes.hex" {
- const some_bytes = "\xCA\xFE\xBA\xBE";
- try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
- try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
- //Test Slices
- try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
- try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
- const bytes_with_zeros = "\x00\x0E\xBA\xBE";
- try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
-}
-
-fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
- var buf: [100]u8 = undefined;
- const result = try bufPrint(buf[0..], template, args);
- if (mem.eql(u8, result, expected)) return;
-
- std.debug.warn("\n====== expected this output: =========\n", .{});
- std.debug.warn("{}", .{expected});
- std.debug.warn("\n======== instead found this: =========\n", .{});
- std.debug.warn("{}", .{result});
- std.debug.warn("\n======================================\n", .{});
- return error.TestFailed;
-}
-
-pub fn trim(buf: []const u8) []const u8 {
- var start: usize = 0;
- while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
-
- var end: usize = buf.len;
- while (true) {
- if (end > start) {
- const new_end = end - 1;
- if (isWhiteSpace(buf[new_end])) {
- end = new_end;
- continue;
- }
- }
- break;
- }
- return buf[start..end];
-}
-
-test "trim" {
- std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
- std.testing.expect(mem.eql(u8, "", trim(" ")));
- std.testing.expect(mem.eql(u8, "", trim("")));
- std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
- std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
-}
-
-pub fn isWhiteSpace(byte: u8) bool {
- return switch (byte) {
- ' ', '\t', '\n', '\r' => true,
- else => false,
- };
-}
-
-pub fn hexToBytes(out: []u8, input: []const u8) !void {
- if (out.len * 2 < input.len)
- return error.InvalidLength;
-
- var in_i: usize = 0;
- while (in_i != input.len) : (in_i += 2) {
- const hi = try charToDigit(input[in_i], 16);
- const lo = try charToDigit(input[in_i + 1], 16);
- out[in_i / 2] = (hi << 4) | lo;
- }
-}
-
-test "hexToBytes" {
- const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
- var pb: [32]u8 = undefined;
- try hexToBytes(pb[0..], test_hex_str);
- try testFmt(test_hex_str, "{X}", .{pb});
-}
-
-test "formatIntValue with comptime_int" {
- const value: comptime_int = 123456789123456789;
-
- var buf = std.ArrayList(u8).init(std.testing.allocator);
- defer buf.deinit();
- try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
- std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
-}
-
-test "formatType max_depth" {
- const Vec2 = struct {
- const SelfType = @This();
- x: f32,
- y: f32,
-
- pub fn format(
- self: SelfType,
- comptime fmt: []const u8,
- options: FormatOptions,
- context: var,
- comptime Errors: type,
- comptime output: fn (@TypeOf(context), []const u8) !void,
- ) !void {
- if (fmt.len == 0) {
- return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
- } else {
- @compileError("Unknown format string: '" ++ fmt ++ "'");
- }
- }
- };
- const E = enum {
- One,
- Two,
- Three,
- };
- const TU = union(enum) {
- const SelfType = @This();
- float: f32,
- int: u32,
- ptr: ?*SelfType,
- };
- const S = struct {
- const SelfType = @This();
- a: ?*SelfType,
- tu: TU,
- e: E,
- vec: Vec2,
- };
-
- var inst = S{
- .a = null,
- .tu = TU{ .ptr = null },
- .e = E.Two,
- .vec = Vec2{ .x = 10.2, .y = 2.22 },
- };
- inst.a = &inst;
- inst.tu.ptr = &inst.tu;
-
- var buf0 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf0.deinit();
- try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
- std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
-
- var buf1 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf1.deinit();
- try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
- std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
-
- var buf2 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf2.deinit();
- try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
- std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
-
- var buf3 = std.ArrayList(u8).init(std.testing.allocator);
- defer buf3.deinit();
- try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
- std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
-}
-
-test "positional" {
- try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
- try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
- try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
- try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
- try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
-}
-
-test "positional with specifier" {
- try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
-}
-
-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});
-}
-
-test "enum-literal" {
- try testFmt(".hello_world", "{}", .{.hello_world});
-}
+// test "parse u64 digit too big" {
+// _ = parseUnsigned(u64, "123a", 10) catch |err| {
+// if (err == error.InvalidCharacter) return;
+// unreachable;
+// };
+// unreachable;
+// }
+
+// test "parse unsigned comptime" {
+// comptime {
+// std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2);
+// }
+// }
+
+// test "optional" {
+// {
+// const value: ?i32 = 1234;
+// try testFmt("optional: 1234\n", "optional: {}\n", .{value});
+// }
+// {
+// const value: ?i32 = null;
+// try testFmt("optional: null\n", "optional: {}\n", .{value});
+// }
+// }
+
+// test "error" {
+// {
+// const value: anyerror!i32 = 1234;
+// try testFmt("error union: 1234\n", "error union: {}\n", .{value});
+// }
+// {
+// const value: anyerror!i32 = error.InvalidChar;
+// try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value});
+// }
+// }
+
+// test "int.small" {
+// {
+// const value: u3 = 0b101;
+// try testFmt("u3: 5\n", "u3: {}\n", .{value});
+// }
+// }
+
+// test "int.specifier" {
+// {
+// const value: u8 = 'a';
+// try testFmt("u8: a\n", "u8: {c}\n", .{value});
+// }
+// {
+// const value: u8 = 0b1100;
+// try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value});
+// }
+// }
+
+// test "int.padded" {
+// try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)});
+// try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)});
+// }
+
+// test "buffer" {
+// {
+// var buf1: [32]u8 = undefined;
+// var context = BufPrintContext{ .remaining = buf1[0..] };
+// try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+// var res = buf1[0 .. buf1.len - context.remaining.len];
+// std.testing.expect(mem.eql(u8, res, "1234"));
+
+// context = BufPrintContext{ .remaining = buf1[0..] };
+// try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+// res = buf1[0 .. buf1.len - context.remaining.len];
+// std.testing.expect(mem.eql(u8, res, "a"));
+
+// context = BufPrintContext{ .remaining = buf1[0..] };
+// try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth);
+// res = buf1[0 .. buf1.len - context.remaining.len];
+// std.testing.expect(mem.eql(u8, res, "1100"));
+// }
+// }
+
+// test "array" {
+// {
+// const value: [3]u8 = "abc".*;
+// try testFmt("array: abc\n", "array: {}\n", .{value});
+// try testFmt("array: abc\n", "array: {}\n", .{&value});
+
+// var buf: [100]u8 = undefined;
+// try testFmt(
+// try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}),
+// "array: {*}\n",
+// .{&value},
+// );
+// }
+// }
+
+// test "slice" {
+// {
+// const value: []const u8 = "abc";
+// try testFmt("slice: abc\n", "slice: {}\n", .{value});
+// }
+// {
+// const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0];
+// try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value});
+// }
+
+// try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"});
+// try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"});
+// }
+
+// test "pointer" {
+// {
+// const value = @intToPtr(*align(1) i32, 0xdeadbeef);
+// try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value});
+// try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value});
+// }
+// {
+// const value = @intToPtr(fn () void, 0xdeadbeef);
+// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+// }
+// {
+// const value = @intToPtr(fn () void, 0xdeadbeef);
+// try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value});
+// }
+// }
+
+// test "cstr" {
+// try testFmt(
+// "cstr: Test C\n",
+// "cstr: {s}\n",
+// .{@ptrCast([*c]const u8, "Test C")},
+// );
+// try testFmt(
+// "cstr: Test C \n",
+// "cstr: {s:10}\n",
+// .{@ptrCast([*c]const u8, "Test C")},
+// );
+// }
+
+// test "filesize" {
+// try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)});
+// try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)});
+// }
+
+// test "struct" {
+// {
+// const Struct = struct {
+// field: u8,
+// };
+// const value = Struct{ .field = 42 };
+// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value});
+// try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
+// }
+// {
+// const Struct = struct {
+// a: u0,
+// b: u1,
+// };
+// const value = Struct{ .a = 0, .b = 1 };
+// try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value});
+// }
+// }
+
+// test "enum" {
+// const Enum = enum {
+// One,
+// Two,
+// };
+// const value = Enum.Two;
+// try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value});
+// 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)});
+// try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)});
+// try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)});
+// }
+
+// test "float.scientific.precision" {
+// try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)});
+// try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))});
+// try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))});
+// // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05.
+// // In fact, libc doesn't round a lot of 5 cases up when one past the precision point.
+// try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))});
+// }
+
+// test "float.special" {
+// try testFmt("f64: nan", "f64: {}", .{math.nan_f64});
+// // negative nan is not defined by IEE 754,
+// // and ARM thus normalizes it to positive nan
+// if (builtin.arch != builtin.Arch.arm) {
+// try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64});
+// }
+// try testFmt("f64: inf", "f64: {}", .{math.inf_f64});
+// try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64});
+// }
+
+// test "float.decimal" {
+// try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)});
+// try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)});
+// try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)});
+// try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)});
+// // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64).
+// // -11.12339... is rounded back up to -11.1234
+// try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)});
+// try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)});
+// try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)});
+// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)});
+// try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)});
+// try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)});
+// try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)});
+// try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)});
+// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)});
+// try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)});
+// }
+
+// test "float.libc.sanity" {
+// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))});
+// try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))});
+// try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))});
+// try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))});
+// try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))});
+
+// // libc differences
+// //
+// // This is 0.015625 exactly according to gdb. We thus round down,
+// // however glibc rounds up for some reason. This occurs for all
+// // floats of the form x.yyyy25 on a precision point.
+// try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))});
+// // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3
+// // also rounds to 630 so I'm inclined to believe libc is not
+// // optimal here.
+// try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))});
+// }
+
+// test "custom" {
+// const Vec2 = struct {
+// const SelfType = @This();
+// x: f32,
+// y: f32,
+
+// pub fn format(
+// self: SelfType,
+// comptime fmt: []const u8,
+// options: FormatOptions,
+// context: var,
+// comptime Errors: type,
+// comptime output: fn (@TypeOf(context), []const u8) !void,
+// ) !void {
+// if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) {
+// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
+// } else if (comptime std.mem.eql(u8, fmt, "d")) {
+// return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y });
+// } else {
+// @compileError("Unknown format character: '" ++ fmt ++ "'");
+// }
+// }
+// };
+
+// var buf1: [32]u8 = undefined;
+// var value = Vec2{
+// .x = 10.2,
+// .y = 2.22,
+// };
+// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value});
+// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value});
+
+// // same thing but not passing a pointer
+// try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value});
+// try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value});
+// }
+
+// test "struct" {
+// const S = struct {
+// a: u32,
+// b: anyerror,
+// };
+
+// const inst = S{
+// .a = 456,
+// .b = error.Unused,
+// };
+
+// try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst});
+// }
+
+// test "union" {
+// const TU = union(enum) {
+// float: f32,
+// int: u32,
+// };
+
+// const UU = union {
+// float: f32,
+// int: u32,
+// };
+
+// const EU = extern union {
+// float: f32,
+// int: u32,
+// };
+
+// const tu_inst = TU{ .int = 123 };
+// const uu_inst = UU{ .int = 456 };
+// const eu_inst = EU{ .float = 321.123 };
+
+// try testFmt("TU{ .int = 123 }", "{}", .{tu_inst});
+
+// var buf: [100]u8 = undefined;
+// const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst});
+// std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@"));
+
+// const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst});
+// std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@"));
+// }
+
+// test "enum" {
+// const E = enum {
+// One,
+// Two,
+// Three,
+// };
+
+// const inst = E.Two;
+
+// try testFmt("E.Two", "{}", .{inst});
+// }
+
+// test "struct.self-referential" {
+// const S = struct {
+// const SelfType = @This();
+// a: ?*SelfType,
+// };
+
+// var inst = S{
+// .a = null,
+// };
+// inst.a = &inst;
+
+// try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst});
+// }
+
+// test "struct.zero-size" {
+// const A = struct {
+// fn foo() void {}
+// };
+// const B = struct {
+// a: A,
+// c: i32,
+// };
+
+// const a = A{};
+// const b = B{ .a = a, .c = 0 };
+
+// try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b});
+// }
+
+// test "bytes.hex" {
+// const some_bytes = "\xCA\xFE\xBA\xBE";
+// try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes});
+// try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes});
+// //Test Slices
+// try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]});
+// try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]});
+// const bytes_with_zeros = "\x00\x0E\xBA\xBE";
+// try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros});
+// }
+
+// fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void {
+// var buf: [100]u8 = undefined;
+// const result = try bufPrint(buf[0..], template, args);
+// if (mem.eql(u8, result, expected)) return;
+
+// std.debug.warn("\n====== expected this output: =========\n", .{});
+// std.debug.warn("{}", .{expected});
+// std.debug.warn("\n======== instead found this: =========\n", .{});
+// std.debug.warn("{}", .{result});
+// std.debug.warn("\n======================================\n", .{});
+// return error.TestFailed;
+// }
+
+// pub fn trim(buf: []const u8) []const u8 {
+// var start: usize = 0;
+// while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {}
+
+// var end: usize = buf.len;
+// while (true) {
+// if (end > start) {
+// const new_end = end - 1;
+// if (isWhiteSpace(buf[new_end])) {
+// end = new_end;
+// continue;
+// }
+// }
+// break;
+// }
+// return buf[start..end];
+// }
+
+// test "trim" {
+// std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t")));
+// std.testing.expect(mem.eql(u8, "", trim(" ")));
+// std.testing.expect(mem.eql(u8, "", trim("")));
+// std.testing.expect(mem.eql(u8, "abc", trim(" abc")));
+// std.testing.expect(mem.eql(u8, "abc", trim("abc ")));
+// }
+
+// pub fn isWhiteSpace(byte: u8) bool {
+// return switch (byte) {
+// ' ', '\t', '\n', '\r' => true,
+// else => false,
+// };
+// }
+
+// pub fn hexToBytes(out: []u8, input: []const u8) !void {
+// if (out.len * 2 < input.len)
+// return error.InvalidLength;
+
+// var in_i: usize = 0;
+// while (in_i != input.len) : (in_i += 2) {
+// const hi = try charToDigit(input[in_i], 16);
+// const lo = try charToDigit(input[in_i + 1], 16);
+// out[in_i / 2] = (hi << 4) | lo;
+// }
+// }
+
+// test "hexToBytes" {
+// const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706";
+// var pb: [32]u8 = undefined;
+// try hexToBytes(pb[0..], test_hex_str);
+// try testFmt(test_hex_str, "{X}", .{pb});
+// }
+
+// test "formatIntValue with comptime_int" {
+// const value: comptime_int = 123456789123456789;
+
+// var buf = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf.deinit();
+// try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice);
+// std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789"));
+// }
+
+// test "formatType max_depth" {
+// const Vec2 = struct {
+// const SelfType = @This();
+// x: f32,
+// y: f32,
+
+// pub fn format(
+// self: SelfType,
+// comptime fmt: []const u8,
+// options: FormatOptions,
+// context: var,
+// comptime Errors: type,
+// comptime output: fn (@TypeOf(context), []const u8) !void,
+// ) !void {
+// if (fmt.len == 0) {
+// return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y });
+// } else {
+// @compileError("Unknown format string: '" ++ fmt ++ "'");
+// }
+// }
+// };
+// const E = enum {
+// One,
+// Two,
+// Three,
+// };
+// const TU = union(enum) {
+// const SelfType = @This();
+// float: f32,
+// int: u32,
+// ptr: ?*SelfType,
+// };
+// const S = struct {
+// const SelfType = @This();
+// a: ?*SelfType,
+// tu: TU,
+// e: E,
+// vec: Vec2,
+// };
+
+// var inst = S{
+// .a = null,
+// .tu = TU{ .ptr = null },
+// .e = E.Two,
+// .vec = Vec2{ .x = 10.2, .y = 2.22 },
+// };
+// inst.a = &inst;
+// inst.tu.ptr = &inst.tu;
+
+// var buf0 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf0.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0);
+// std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }"));
+
+// var buf1 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf1.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1);
+// std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+// var buf2 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf2.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2);
+// std.testing.expect(mem.eql(u8, buf2.toSlice(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }"));
+
+// var buf3 = std.ArrayList(u8).init(std.testing.allocator);
+// defer buf3.deinit();
+// try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3);
+// std.testing.expect(mem.eql(u8, buf3.toSlice(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }"));
+// }
+
+// test "positional" {
+// try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+// try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) });
+// try testFmt("0 0", "{0} {0}", .{@as(usize, 0)});
+// try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) });
+// try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) });
+// }
+
+// test "positional with specifier" {
+// try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)});
+// }
+
+// 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});
+// }
+
+// test "enum-literal" {
+// try testFmt(".hello_world", "{}", .{.hello_world});
+// }