| ... | @@ -972,20 +972,9 @@ fn formatIntUnsigned( | ... | @@ -972,20 +972,9 @@ fn formatIntUnsigned( |
| 972 | } | 972 | } |
| 973 | | 973 | |
| 974 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize { | 974 | pub fn formatIntBuf(out_buf: []u8, value: var, base: u8, uppercase: bool, options: FormatOptions) usize { |
| 975 | var context = FormatIntBuf{ | 975 | var fbs = std.io.fixedBufferStream(out_buf); |
| 976 | .out_buf = out_buf, | 976 | formatInt(value, base, uppercase, options, fbs.outStream()) catch unreachable; |
| 977 | .index = 0, | 977 | return fbs.pos; |
| 978 | }; | | |
| 979 | formatInt(value, base, uppercase, options, &context, error{}, formatIntCallback) catch unreachable; | | |
| 980 | return context.index; | | |
| 981 | } | | |
| 982 | const FormatIntBuf = struct { | | |
| 983 | out_buf: []u8, | | |
| 984 | index: usize, | | |
| 985 | }; | | |
| 986 | fn formatIntCallback(context: *FormatIntBuf, bytes: []const u8) (error{}!void) { | | |
| 987 | mem.copy(u8, context.out_buf[context.index..], bytes); | | |
| 988 | context.index += bytes.len; | | |
| 989 | } | 978 | } |
| 990 | | 979 | |
| 991 | pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { | 980 | pub fn parseInt(comptime T: type, buf: []const u8, radix: u8) !T { |
| ... | @@ -1085,48 +1074,48 @@ fn digitToChar(digit: u8, uppercase: bool) u8 { | ... | @@ -1085,48 +1074,48 @@ fn digitToChar(digit: u8, uppercase: bool) u8 { |
| 1085 | }; | 1074 | }; |
| 1086 | } | 1075 | } |
| 1087 | | 1076 | |
| 1088 | const BufPrintContext = struct { | 1077 | // const BufPrintContext = struct { |
| 1089 | remaining: []u8, | 1078 | // remaining: []u8, |
| 1090 | }; | 1079 | // }; |
| 1091 | | 1080 | |
| 1092 | fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void { | 1081 | // fn bufPrintWrite(context: *BufPrintContext, bytes: []const u8) !void { |
| 1093 | if (context.remaining.len < bytes.len) { | 1082 | // if (context.remaining.len < bytes.len) { |
| 1094 | mem.copy(u8, context.remaining, bytes[0..context.remaining.len]); | 1083 | // mem.copy(u8, context.remaining, bytes[0..context.remaining.len]); |
| 1095 | return error.BufferTooSmall; | 1084 | // return error.BufferTooSmall; |
| 1096 | } | 1085 | // } |
| 1097 | mem.copy(u8, context.remaining, bytes); | 1086 | // mem.copy(u8, context.remaining, bytes); |
| 1098 | context.remaining = context.remaining[bytes.len..]; | 1087 | // context.remaining = context.remaining[bytes.len..]; |
| 1099 | } | 1088 | // } |
| 1100 | | 1089 | |
| 1101 | pub const BufPrintError = error{ | 1090 | // pub const BufPrintError = error{ |
| 1102 | /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes. | 1091 | // /// As much as possible was written to the buffer, but it was too small to fit all the printed bytes. |
| 1103 | BufferTooSmall, | 1092 | // BufferTooSmall, |
| 1104 | }; | 1093 | // }; |
| 1105 | pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 { | 1094 | // pub fn bufPrint(buf: []u8, comptime fmt: []const u8, args: var) BufPrintError![]u8 { |
| 1106 | var context = BufPrintContext{ .remaining = buf }; | 1095 | // var context = BufPrintContext{ .remaining = buf }; |
| 1107 | try format(&context, BufPrintError, bufPrintWrite, fmt, args); | 1096 | // try format(&context, BufPrintError, bufPrintWrite, fmt, args); |
| 1108 | return buf[0 .. buf.len - context.remaining.len]; | 1097 | // return buf[0 .. buf.len - context.remaining.len]; |
| 1109 | } | 1098 | // } |
| 1110 | | 1099 | |
| 1111 | pub const AllocPrintError = error{OutOfMemory}; | 1100 | // pub const AllocPrintError = error{OutOfMemory}; |
| 1112 | | 1101 | |
| 1113 | pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 { | 1102 | // pub fn allocPrint(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![]u8 { |
| 1114 | var size: usize = 0; | 1103 | // var size: usize = 0; |
| 1115 | format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; | 1104 | // format(&size, error{}, countSize, fmt, args) catch |err| switch (err) {}; |
| 1116 | const buf = try allocator.alloc(u8, size); | 1105 | // const buf = try allocator.alloc(u8, size); |
| 1117 | return bufPrint(buf, fmt, args) catch |err| switch (err) { | 1106 | // return bufPrint(buf, fmt, args) catch |err| switch (err) { |
| 1118 | error.BufferTooSmall => unreachable, // we just counted the size above | 1107 | // error.BufferTooSmall => unreachable, // we just counted the size above |
| 1119 | }; | 1108 | // }; |
| 1120 | } | 1109 | // } |
| 1121 | | 1110 | |
| 1122 | fn countSize(size: *usize, bytes: []const u8) (error{}!void) { | 1111 | // fn countSize(size: *usize, bytes: []const u8) (error{}!void) { |
| 1123 | size.* += bytes.len; | 1112 | // size.* += bytes.len; |
| 1124 | } | 1113 | // } |
| 1125 | | 1114 | |
| 1126 | pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 { | 1115 | // pub fn allocPrint0(allocator: *mem.Allocator, comptime fmt: []const u8, args: var) AllocPrintError![:0]u8 { |
| 1127 | const result = try allocPrint(allocator, fmt ++ "\x00", args); | 1116 | // const result = try allocPrint(allocator, fmt ++ "\x00", args); |
| 1128 | return result[0 .. result.len - 1 :0]; | 1117 | // return result[0 .. result.len - 1 :0]; |
| 1129 | } | 1118 | // } |
| 1130 | | 1119 | |
| 1131 | test "bufPrintInt" { | 1120 | test "bufPrintInt" { |
| 1132 | var buffer: [100]u8 = undefined; | 1121 | var buffer: [100]u8 = undefined; |
| ... | @@ -1153,566 +1142,566 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: | ... | @@ -1153,566 +1142,566 @@ fn bufPrintIntToSlice(buf: []u8, value: var, base: u8, uppercase: bool, options: |
| 1153 | return buf[0..formatIntBuf(buf, value, base, uppercase, options)]; | 1142 | return buf[0..formatIntBuf(buf, value, base, uppercase, options)]; |
| 1154 | } | 1143 | } |
| 1155 | | 1144 | |
| 1156 | test "parse u64 digit too big" { | 1145 | // test "parse u64 digit too big" { |
| 1157 | _ = parseUnsigned(u64, "123a", 10) catch |err| { | 1146 | // _ = parseUnsigned(u64, "123a", 10) catch |err| { |
| 1158 | if (err == error.InvalidCharacter) return; | 1147 | // if (err == error.InvalidCharacter) return; |
| 1159 | unreachable; | 1148 | // unreachable; |
| 1160 | }; | 1149 | // }; |
| 1161 | unreachable; | 1150 | // unreachable; |
| 1162 | } | 1151 | // } |
| 1163 | | 1152 | |
| 1164 | test "parse unsigned comptime" { | 1153 | // test "parse unsigned comptime" { |
| 1165 | comptime { | 1154 | // comptime { |
| 1166 | std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2); | 1155 | // std.testing.expect((try parseUnsigned(usize, "2", 10)) == 2); |
| 1167 | } | 1156 | // } |
| 1168 | } | 1157 | // } |
| 1169 | | 1158 | |
| 1170 | test "optional" { | 1159 | // test "optional" { |
| 1171 | { | 1160 | // { |
| 1172 | const value: ?i32 = 1234; | 1161 | // const value: ?i32 = 1234; |
| 1173 | try testFmt("optional: 1234\n", "optional: {}\n", .{value}); | 1162 | // try testFmt("optional: 1234\n", "optional: {}\n", .{value}); |
| 1174 | } | 1163 | // } |
| 1175 | { | 1164 | // { |
| 1176 | const value: ?i32 = null; | 1165 | // const value: ?i32 = null; |
| 1177 | try testFmt("optional: null\n", "optional: {}\n", .{value}); | 1166 | // try testFmt("optional: null\n", "optional: {}\n", .{value}); |
| 1178 | } | 1167 | // } |
| 1179 | } | 1168 | // } |
| 1180 | | 1169 | |
| 1181 | test "error" { | 1170 | // test "error" { |
| 1182 | { | 1171 | // { |
| 1183 | const value: anyerror!i32 = 1234; | 1172 | // const value: anyerror!i32 = 1234; |
| 1184 | try testFmt("error union: 1234\n", "error union: {}\n", .{value}); | 1173 | // try testFmt("error union: 1234\n", "error union: {}\n", .{value}); |
| 1185 | } | 1174 | // } |
| 1186 | { | 1175 | // { |
| 1187 | const value: anyerror!i32 = error.InvalidChar; | 1176 | // const value: anyerror!i32 = error.InvalidChar; |
| 1188 | try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value}); | 1177 | // try testFmt("error union: error.InvalidChar\n", "error union: {}\n", .{value}); |
| 1189 | } | 1178 | // } |
| 1190 | } | 1179 | // } |
| 1191 | | 1180 | |
| 1192 | test "int.small" { | 1181 | // test "int.small" { |
| 1193 | { | 1182 | // { |
| 1194 | const value: u3 = 0b101; | 1183 | // const value: u3 = 0b101; |
| 1195 | try testFmt("u3: 5\n", "u3: {}\n", .{value}); | 1184 | // try testFmt("u3: 5\n", "u3: {}\n", .{value}); |
| 1196 | } | 1185 | // } |
| 1197 | } | 1186 | // } |
| 1198 | | 1187 | |
| 1199 | test "int.specifier" { | 1188 | // test "int.specifier" { |
| 1200 | { | 1189 | // { |
| 1201 | const value: u8 = 'a'; | 1190 | // const value: u8 = 'a'; |
| 1202 | try testFmt("u8: a\n", "u8: {c}\n", .{value}); | 1191 | // try testFmt("u8: a\n", "u8: {c}\n", .{value}); |
| 1203 | } | 1192 | // } |
| 1204 | { | 1193 | // { |
| 1205 | const value: u8 = 0b1100; | 1194 | // const value: u8 = 0b1100; |
| 1206 | try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value}); | 1195 | // try testFmt("u8: 0b1100\n", "u8: 0b{b}\n", .{value}); |
| 1207 | } | 1196 | // } |
| 1208 | } | 1197 | // } |
| 1209 | | 1198 | |
| 1210 | test "int.padded" { | 1199 | // test "int.padded" { |
| 1211 | try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)}); | 1200 | // try testFmt("u8: ' 1'", "u8: '{:4}'", .{@as(u8, 1)}); |
| 1212 | try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)}); | 1201 | // try testFmt("u8: 'xxx1'", "u8: '{:x<4}'", .{@as(u8, 1)}); |
| 1213 | } | 1202 | // } |
| 1214 | | 1203 | |
| 1215 | test "buffer" { | 1204 | // test "buffer" { |
| 1216 | { | 1205 | // { |
| 1217 | var buf1: [32]u8 = undefined; | 1206 | // var buf1: [32]u8 = undefined; |
| 1218 | var context = BufPrintContext{ .remaining = buf1[0..] }; | 1207 | // var context = BufPrintContext{ .remaining = buf1[0..] }; |
| 1219 | try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); | 1208 | // try formatType(1234, "", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); |
| 1220 | var res = buf1[0 .. buf1.len - context.remaining.len]; | 1209 | // var res = buf1[0 .. buf1.len - context.remaining.len]; |
| 1221 | std.testing.expect(mem.eql(u8, res, "1234")); | 1210 | // std.testing.expect(mem.eql(u8, res, "1234")); |
| 1222 | | 1211 | |
| 1223 | context = BufPrintContext{ .remaining = buf1[0..] }; | 1212 | // context = BufPrintContext{ .remaining = buf1[0..] }; |
| 1224 | try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); | 1213 | // try formatType('a', "c", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); |
| 1225 | res = buf1[0 .. buf1.len - context.remaining.len]; | 1214 | // res = buf1[0 .. buf1.len - context.remaining.len]; |
| 1226 | std.testing.expect(mem.eql(u8, res, "a")); | 1215 | // std.testing.expect(mem.eql(u8, res, "a")); |
| 1227 | | 1216 | |
| 1228 | context = BufPrintContext{ .remaining = buf1[0..] }; | 1217 | // context = BufPrintContext{ .remaining = buf1[0..] }; |
| 1229 | try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); | 1218 | // try formatType(0b1100, "b", FormatOptions{}, &context, error{BufferTooSmall}, bufPrintWrite, default_max_depth); |
| 1230 | res = buf1[0 .. buf1.len - context.remaining.len]; | 1219 | // res = buf1[0 .. buf1.len - context.remaining.len]; |
| 1231 | std.testing.expect(mem.eql(u8, res, "1100")); | 1220 | // std.testing.expect(mem.eql(u8, res, "1100")); |
| 1232 | } | 1221 | // } |
| 1233 | } | 1222 | // } |
| 1234 | | 1223 | |
| 1235 | test "array" { | 1224 | // test "array" { |
| 1236 | { | 1225 | // { |
| 1237 | const value: [3]u8 = "abc".*; | 1226 | // const value: [3]u8 = "abc".*; |
| 1238 | try testFmt("array: abc\n", "array: {}\n", .{value}); | 1227 | // try testFmt("array: abc\n", "array: {}\n", .{value}); |
| 1239 | try testFmt("array: abc\n", "array: {}\n", .{&value}); | 1228 | // try testFmt("array: abc\n", "array: {}\n", .{&value}); |
| 1240 | | 1229 | |
| 1241 | var buf: [100]u8 = undefined; | 1230 | // var buf: [100]u8 = undefined; |
| 1242 | try testFmt( | 1231 | // try testFmt( |
| 1243 | try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}), | 1232 | // try bufPrint(buf[0..], "array: [3]u8@{x}\n", .{@ptrToInt(&value)}), |
| 1244 | "array: {*}\n", | 1233 | // "array: {*}\n", |
| 1245 | .{&value}, | 1234 | // .{&value}, |
| 1246 | ); | 1235 | // ); |
| 1247 | } | 1236 | // } |
| 1248 | } | 1237 | // } |
| 1249 | | 1238 | |
| 1250 | test "slice" { | 1239 | // test "slice" { |
| 1251 | { | 1240 | // { |
| 1252 | const value: []const u8 = "abc"; | 1241 | // const value: []const u8 = "abc"; |
| 1253 | try testFmt("slice: abc\n", "slice: {}\n", .{value}); | 1242 | // try testFmt("slice: abc\n", "slice: {}\n", .{value}); |
| 1254 | } | 1243 | // } |
| 1255 | { | 1244 | // { |
| 1256 | const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0]; | 1245 | // const value = @intToPtr([*]align(1) const []const u8, 0xdeadbeef)[0..0]; |
| 1257 | try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value}); | 1246 | // try testFmt("slice: []const u8@deadbeef\n", "slice: {}\n", .{value}); |
| 1258 | } | 1247 | // } |
| 1259 | | 1248 | |
| 1260 | try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"}); | 1249 | // try testFmt("buf: Test \n", "buf: {s:5}\n", .{"Test"}); |
| 1261 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); | 1250 | // try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", .{"Test"}); |
| 1262 | } | 1251 | // } |
| 1263 | | 1252 | |
| 1264 | test "pointer" { | 1253 | // test "pointer" { |
| 1265 | { | 1254 | // { |
| 1266 | const value = @intToPtr(*align(1) i32, 0xdeadbeef); | 1255 | // const value = @intToPtr(*align(1) i32, 0xdeadbeef); |
| 1267 | try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value}); | 1256 | // try testFmt("pointer: i32@deadbeef\n", "pointer: {}\n", .{value}); |
| 1268 | try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value}); | 1257 | // try testFmt("pointer: i32@deadbeef\n", "pointer: {*}\n", .{value}); |
| 1269 | } | 1258 | // } |
| 1270 | { | 1259 | // { |
| 1271 | const value = @intToPtr(fn () void, 0xdeadbeef); | 1260 | // const value = @intToPtr(fn () void, 0xdeadbeef); |
| 1272 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); | 1261 | // try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); |
| 1273 | } | 1262 | // } |
| 1274 | { | 1263 | // { |
| 1275 | const value = @intToPtr(fn () void, 0xdeadbeef); | 1264 | // const value = @intToPtr(fn () void, 0xdeadbeef); |
| 1276 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); | 1265 | // try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", .{value}); |
| 1277 | } | 1266 | // } |
| 1278 | } | 1267 | // } |
| 1279 | | 1268 | |
| 1280 | test "cstr" { | 1269 | // test "cstr" { |
| 1281 | try testFmt( | 1270 | // try testFmt( |
| 1282 | "cstr: Test C\n", | 1271 | // "cstr: Test C\n", |
| 1283 | "cstr: {s}\n", | 1272 | // "cstr: {s}\n", |
| 1284 | .{@ptrCast([*c]const u8, "Test C")}, | 1273 | // .{@ptrCast([*c]const u8, "Test C")}, |
| 1285 | ); | 1274 | // ); |
| 1286 | try testFmt( | 1275 | // try testFmt( |
| 1287 | "cstr: Test C \n", | 1276 | // "cstr: Test C \n", |
| 1288 | "cstr: {s:10}\n", | 1277 | // "cstr: {s:10}\n", |
| 1289 | .{@ptrCast([*c]const u8, "Test C")}, | 1278 | // .{@ptrCast([*c]const u8, "Test C")}, |
| 1290 | ); | 1279 | // ); |
| 1291 | } | 1280 | // } |
| 1292 | | 1281 | |
| 1293 | test "filesize" { | 1282 | // test "filesize" { |
| 1294 | try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)}); | 1283 | // try testFmt("file size: 63MiB\n", "file size: {Bi}\n", .{@as(usize, 63 * 1024 * 1024)}); |
| 1295 | try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)}); | 1284 | // try testFmt("file size: 66.06MB\n", "file size: {B:.2}\n", .{@as(usize, 63 * 1024 * 1024)}); |
| 1296 | } | 1285 | // } |
| 1297 | | 1286 | |
| 1298 | test "struct" { | 1287 | // test "struct" { |
| 1299 | { | 1288 | // { |
| 1300 | const Struct = struct { | 1289 | // const Struct = struct { |
| 1301 | field: u8, | 1290 | // field: u8, |
| 1302 | }; | 1291 | // }; |
| 1303 | const value = Struct{ .field = 42 }; | 1292 | // const value = Struct{ .field = 42 }; |
| 1304 | try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value}); | 1293 | // try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{value}); |
| 1305 | try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value}); | 1294 | // try testFmt("struct: Struct{ .field = 42 }\n", "struct: {}\n", .{&value}); |
| 1306 | } | 1295 | // } |
| 1307 | { | 1296 | // { |
| 1308 | const Struct = struct { | 1297 | // const Struct = struct { |
| 1309 | a: u0, | 1298 | // a: u0, |
| 1310 | b: u1, | 1299 | // b: u1, |
| 1311 | }; | 1300 | // }; |
| 1312 | const value = Struct{ .a = 0, .b = 1 }; | 1301 | // const value = Struct{ .a = 0, .b = 1 }; |
| 1313 | try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); | 1302 | // try testFmt("struct: Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); |
| 1314 | } | 1303 | // } |
| 1315 | } | 1304 | // } |
| 1316 | | 1305 | |
| 1317 | test "enum" { | 1306 | // test "enum" { |
| 1318 | const Enum = enum { | 1307 | // const Enum = enum { |
| 1319 | One, | 1308 | // One, |
| 1320 | Two, | 1309 | // Two, |
| 1321 | }; | 1310 | // }; |
| 1322 | const value = Enum.Two; | 1311 | // const value = Enum.Two; |
| 1323 | try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value}); | 1312 | // try testFmt("enum: Enum.Two\n", "enum: {}\n", .{value}); |
| 1324 | try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value}); | 1313 | // try testFmt("enum: Enum.Two\n", "enum: {}\n", .{&value}); |
| 1325 | } | 1314 | // } |
| 1326 | | 1315 | |
| 1327 | test "non-exhaustive enum" { | 1316 | // test "non-exhaustive enum" { |
| 1328 | const Enum = enum(u16) { | 1317 | // const Enum = enum(u16) { |
| 1329 | One = 0x000f, | 1318 | // One = 0x000f, |
| 1330 | Two = 0xbeef, | 1319 | // Two = 0xbeef, |
| 1331 | _, | 1320 | // _, |
| 1332 | }; | 1321 | // }; |
| 1333 | try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One}); | 1322 | // try testFmt("enum: Enum(15)\n", "enum: {}\n", .{Enum.One}); |
| 1334 | try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two}); | 1323 | // try testFmt("enum: Enum(48879)\n", "enum: {}\n", .{Enum.Two}); |
| 1335 | try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); | 1324 | // try testFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); |
| 1336 | try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); | 1325 | // try testFmt("enum: Enum(f)\n", "enum: {x}\n", .{Enum.One}); |
| 1337 | try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); | 1326 | // try testFmt("enum: Enum(beef)\n", "enum: {x}\n", .{Enum.Two}); |
| 1338 | try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); | 1327 | // try testFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); |
| 1339 | } | 1328 | // } |
| 1340 | | 1329 | |
| 1341 | test "float.scientific" { | 1330 | // test "float.scientific" { |
| 1342 | try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)}); | 1331 | // try testFmt("f32: 1.34000003e+00", "f32: {e}", .{@as(f32, 1.34)}); |
| 1343 | try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)}); | 1332 | // try testFmt("f32: 1.23400001e+01", "f32: {e}", .{@as(f32, 12.34)}); |
| 1344 | try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)}); | 1333 | // try testFmt("f64: -1.234e+11", "f64: {e}", .{@as(f64, -12.34e10)}); |
| 1345 | try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)}); | 1334 | // try testFmt("f64: 9.99996e-40", "f64: {e}", .{@as(f64, 9.999960e-40)}); |
| 1346 | } | 1335 | // } |
| 1347 | | 1336 | |
| 1348 | test "float.scientific.precision" { | 1337 | // test "float.scientific.precision" { |
| 1349 | try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)}); | 1338 | // try testFmt("f64: 1.40971e-42", "f64: {e:.5}", .{@as(f64, 1.409706e-42)}); |
| 1350 | try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))}); | 1339 | // try testFmt("f64: 1.00000e-09", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 814313563)))}); |
| 1351 | try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))}); | 1340 | // try testFmt("f64: 7.81250e-03", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1006632960)))}); |
| 1352 | // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05. | 1341 | // // libc rounds 1.000005e+05 to 1.00000e+05 but zig does 1.00001e+05. |
| 1353 | // In fact, libc doesn't round a lot of 5 cases up when one past the precision point. | 1342 | // // In fact, libc doesn't round a lot of 5 cases up when one past the precision point. |
| 1354 | try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))}); | 1343 | // try testFmt("f64: 1.00001e+05", "f64: {e:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1203982400)))}); |
| 1355 | } | 1344 | // } |
| 1356 | | 1345 | |
| 1357 | test "float.special" { | 1346 | // test "float.special" { |
| 1358 | try testFmt("f64: nan", "f64: {}", .{math.nan_f64}); | 1347 | // try testFmt("f64: nan", "f64: {}", .{math.nan_f64}); |
| 1359 | // negative nan is not defined by IEE 754, | 1348 | // // negative nan is not defined by IEE 754, |
| 1360 | // and ARM thus normalizes it to positive nan | 1349 | // // and ARM thus normalizes it to positive nan |
| 1361 | if (builtin.arch != builtin.Arch.arm) { | 1350 | // if (builtin.arch != builtin.Arch.arm) { |
| 1362 | try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64}); | 1351 | // try testFmt("f64: -nan", "f64: {}", .{-math.nan_f64}); |
| 1363 | } | 1352 | // } |
| 1364 | try testFmt("f64: inf", "f64: {}", .{math.inf_f64}); | 1353 | // try testFmt("f64: inf", "f64: {}", .{math.inf_f64}); |
| 1365 | try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64}); | 1354 | // try testFmt("f64: -inf", "f64: {}", .{-math.inf_f64}); |
| 1366 | } | 1355 | // } |
| 1367 | | 1356 | |
| 1368 | test "float.decimal" { | 1357 | // test "float.decimal" { |
| 1369 | try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); | 1358 | // try testFmt("f64: 152314000000000000000000000000", "f64: {d}", .{@as(f64, 1.52314e+29)}); |
| 1370 | try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); | 1359 | // try testFmt("f32: 0", "f32: {d}", .{@as(f32, 0.0)}); |
| 1371 | try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)}); | 1360 | // try testFmt("f32: 1.1", "f32: {d:.1}", .{@as(f32, 1.1234)}); |
| 1372 | try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)}); | 1361 | // try testFmt("f32: 1234.57", "f32: {d:.2}", .{@as(f32, 1234.567)}); |
| 1373 | // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). | 1362 | // // -11.1234 is converted to f64 -11.12339... internally (errol3() function takes f64). |
| 1374 | // -11.12339... is rounded back up to -11.1234 | 1363 | // // -11.12339... is rounded back up to -11.1234 |
| 1375 | try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)}); | 1364 | // try testFmt("f32: -11.1234", "f32: {d:.4}", .{@as(f32, -11.1234)}); |
| 1376 | try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)}); | 1365 | // try testFmt("f32: 91.12345", "f32: {d:.5}", .{@as(f32, 91.12345)}); |
| 1377 | try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)}); | 1366 | // try testFmt("f64: 91.1234567890", "f64: {d:.10}", .{@as(f64, 91.12345678901235)}); |
| 1378 | try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)}); | 1367 | // try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 0.0)}); |
| 1379 | try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)}); | 1368 | // try testFmt("f64: 6", "f64: {d:.0}", .{@as(f64, 5.700)}); |
| 1380 | try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)}); | 1369 | // try testFmt("f64: 10.0", "f64: {d:.1}", .{@as(f64, 9.999)}); |
| 1381 | try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)}); | 1370 | // try testFmt("f64: 1.000", "f64: {d:.3}", .{@as(f64, 1.0)}); |
| 1382 | try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)}); | 1371 | // try testFmt("f64: 0.00030000", "f64: {d:.8}", .{@as(f64, 0.0003)}); |
| 1383 | try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)}); | 1372 | // try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 1.40130e-45)}); |
| 1384 | try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)}); | 1373 | // try testFmt("f64: 0.00000", "f64: {d:.5}", .{@as(f64, 9.999960e-40)}); |
| 1385 | } | 1374 | // } |
| 1386 | | 1375 | |
| 1387 | test "float.libc.sanity" { | 1376 | // test "float.libc.sanity" { |
| 1388 | try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))}); | 1377 | // try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 916964781)))}); |
| 1389 | try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))}); | 1378 | // try testFmt("f64: 0.00001", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 925353389)))}); |
| 1390 | try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))}); | 1379 | // try testFmt("f64: 0.10000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1036831278)))}); |
| 1391 | try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))}); | 1380 | // try testFmt("f64: 1.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1065353133)))}); |
| 1392 | try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))}); | 1381 | // try testFmt("f64: 10.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1092616192)))}); |
| 1393 | | 1382 | |
| 1394 | // libc differences | 1383 | // // libc differences |
| 1395 | // | 1384 | // // |
| 1396 | // This is 0.015625 exactly according to gdb. We thus round down, | 1385 | // // This is 0.015625 exactly according to gdb. We thus round down, |
| 1397 | // however glibc rounds up for some reason. This occurs for all | 1386 | // // however glibc rounds up for some reason. This occurs for all |
| 1398 | // floats of the form x.yyyy25 on a precision point. | 1387 | // // floats of the form x.yyyy25 on a precision point. |
| 1399 | try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))}); | 1388 | // try testFmt("f64: 0.01563", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1015021568)))}); |
| 1400 | // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3 | 1389 | // // errol3 rounds to ... 630 but libc rounds to ...632. Grisu3 |
| 1401 | // also rounds to 630 so I'm inclined to believe libc is not | 1390 | // // also rounds to 630 so I'm inclined to believe libc is not |
| 1402 | // optimal here. | 1391 | // // optimal here. |
| 1403 | try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))}); | 1392 | // try testFmt("f64: 18014400656965630.00000", "f64: {d:.5}", .{@as(f64, @bitCast(f32, @as(u32, 1518338049)))}); |
| 1404 | } | 1393 | // } |
| 1405 | | 1394 | |
| 1406 | test "custom" { | 1395 | // test "custom" { |
| 1407 | const Vec2 = struct { | 1396 | // const Vec2 = struct { |
| 1408 | const SelfType = @This(); | 1397 | // const SelfType = @This(); |
| 1409 | x: f32, | 1398 | // x: f32, |
| 1410 | y: f32, | 1399 | // y: f32, |
| 1411 | | 1400 | |
| 1412 | pub fn format( | 1401 | // pub fn format( |
| 1413 | self: SelfType, | 1402 | // self: SelfType, |
| 1414 | comptime fmt: []const u8, | 1403 | // comptime fmt: []const u8, |
| 1415 | options: FormatOptions, | 1404 | // options: FormatOptions, |
| 1416 | context: var, | 1405 | // context: var, |
| 1417 | comptime Errors: type, | 1406 | // comptime Errors: type, |
| 1418 | comptime output: fn (@TypeOf(context), []const u8) !void, | 1407 | // comptime output: fn (@TypeOf(context), []const u8) !void, |
| 1419 | ) !void { | 1408 | // ) !void { |
| 1420 | if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) { | 1409 | // if (fmt.len == 0 or comptime std.mem.eql(u8, fmt, "p")) { |
| 1421 | return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); | 1410 | // return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); |
| 1422 | } else if (comptime std.mem.eql(u8, fmt, "d")) { | 1411 | // } else if (comptime std.mem.eql(u8, fmt, "d")) { |
| 1423 | return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y }); | 1412 | // return std.fmtstream.format(out_stream, "{d:.3}x{d:.3}", .{ self.x, self.y }); |
| 1424 | } else { | 1413 | // } else { |
| 1425 | @compileError("Unknown format character: '" ++ fmt ++ "'"); | 1414 | // @compileError("Unknown format character: '" ++ fmt ++ "'"); |
| 1426 | } | 1415 | // } |
| 1427 | } | 1416 | // } |
| 1428 | }; | 1417 | // }; |
| 1429 | | 1418 | |
| 1430 | var buf1: [32]u8 = undefined; | 1419 | // var buf1: [32]u8 = undefined; |
| 1431 | var value = Vec2{ | 1420 | // var value = Vec2{ |
| 1432 | .x = 10.2, | 1421 | // .x = 10.2, |
| 1433 | .y = 2.22, | 1422 | // .y = 2.22, |
| 1434 | }; | 1423 | // }; |
| 1435 | try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value}); | 1424 | // try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{&value}); |
| 1436 | try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value}); | 1425 | // try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{&value}); |
| 1437 | | 1426 | |
| 1438 | // same thing but not passing a pointer | 1427 | // // same thing but not passing a pointer |
| 1439 | try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value}); | 1428 | // try testFmt("point: (10.200,2.220)\n", "point: {}\n", .{value}); |
| 1440 | try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value}); | 1429 | // try testFmt("dim: 10.200x2.220\n", "dim: {d}\n", .{value}); |
| 1441 | } | 1430 | // } |
| 1442 | | 1431 | |
| 1443 | test "struct" { | 1432 | // test "struct" { |
| 1444 | const S = struct { | 1433 | // const S = struct { |
| 1445 | a: u32, | 1434 | // a: u32, |
| 1446 | b: anyerror, | 1435 | // b: anyerror, |
| 1447 | }; | 1436 | // }; |
| 1448 | | 1437 | |
| 1449 | const inst = S{ | 1438 | // const inst = S{ |
| 1450 | .a = 456, | 1439 | // .a = 456, |
| 1451 | .b = error.Unused, | 1440 | // .b = error.Unused, |
| 1452 | }; | 1441 | // }; |
| 1453 | | 1442 | |
| 1454 | try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst}); | 1443 | // try testFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst}); |
| 1455 | } | 1444 | // } |
| 1456 | | 1445 | |
| 1457 | test "union" { | 1446 | // test "union" { |
| 1458 | const TU = union(enum) { | 1447 | // const TU = union(enum) { |
| 1459 | float: f32, | 1448 | // float: f32, |
| 1460 | int: u32, | 1449 | // int: u32, |
| 1461 | }; | 1450 | // }; |
| 1462 | | 1451 | |
| 1463 | const UU = union { | 1452 | // const UU = union { |
| 1464 | float: f32, | 1453 | // float: f32, |
| 1465 | int: u32, | 1454 | // int: u32, |
| 1466 | }; | 1455 | // }; |
| 1467 | | 1456 | |
| 1468 | const EU = extern union { | 1457 | // const EU = extern union { |
| 1469 | float: f32, | 1458 | // float: f32, |
| 1470 | int: u32, | 1459 | // int: u32, |
| 1471 | }; | 1460 | // }; |
| 1472 | | 1461 | |
| 1473 | const tu_inst = TU{ .int = 123 }; | 1462 | // const tu_inst = TU{ .int = 123 }; |
| 1474 | const uu_inst = UU{ .int = 456 }; | 1463 | // const uu_inst = UU{ .int = 456 }; |
| 1475 | const eu_inst = EU{ .float = 321.123 }; | 1464 | // const eu_inst = EU{ .float = 321.123 }; |
| 1476 | | 1465 | |
| 1477 | try testFmt("TU{ .int = 123 }", "{}", .{tu_inst}); | 1466 | // try testFmt("TU{ .int = 123 }", "{}", .{tu_inst}); |
| 1478 | | 1467 | |
| 1479 | var buf: [100]u8 = undefined; | 1468 | // var buf: [100]u8 = undefined; |
| 1480 | const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); | 1469 | // const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); |
| 1481 | std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@")); | 1470 | // std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@")); |
| 1482 | | 1471 | |
| 1483 | const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); | 1472 | // const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); |
| 1484 | std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@")); | 1473 | // std.testing.expect(mem.eql(u8, uu_result[0..3], "EU@")); |
| 1485 | } | 1474 | // } |
| 1486 | | 1475 | |
| 1487 | test "enum" { | 1476 | // test "enum" { |
| 1488 | const E = enum { | 1477 | // const E = enum { |
| 1489 | One, | 1478 | // One, |
| 1490 | Two, | 1479 | // Two, |
| 1491 | Three, | 1480 | // Three, |
| 1492 | }; | 1481 | // }; |
| 1493 | | 1482 | |
| 1494 | const inst = E.Two; | 1483 | // const inst = E.Two; |
| 1495 | | 1484 | |
| 1496 | try testFmt("E.Two", "{}", .{inst}); | 1485 | // try testFmt("E.Two", "{}", .{inst}); |
| 1497 | } | 1486 | // } |
| 1498 | | 1487 | |
| 1499 | test "struct.self-referential" { | 1488 | // test "struct.self-referential" { |
| 1500 | const S = struct { | 1489 | // const S = struct { |
| 1501 | const SelfType = @This(); | 1490 | // const SelfType = @This(); |
| 1502 | a: ?*SelfType, | 1491 | // a: ?*SelfType, |
| 1503 | }; | 1492 | // }; |
| 1504 | | 1493 | |
| 1505 | var inst = S{ | 1494 | // var inst = S{ |
| 1506 | .a = null, | 1495 | // .a = null, |
| 1507 | }; | 1496 | // }; |
| 1508 | inst.a = &inst; | 1497 | // inst.a = &inst; |
| 1509 | | 1498 | |
| 1510 | try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst}); | 1499 | // try testFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst}); |
| 1511 | } | 1500 | // } |
| 1512 | | 1501 | |
| 1513 | test "struct.zero-size" { | 1502 | // test "struct.zero-size" { |
| 1514 | const A = struct { | 1503 | // const A = struct { |
| 1515 | fn foo() void {} | 1504 | // fn foo() void {} |
| 1516 | }; | 1505 | // }; |
| 1517 | const B = struct { | 1506 | // const B = struct { |
| 1518 | a: A, | 1507 | // a: A, |
| 1519 | c: i32, | 1508 | // c: i32, |
| 1520 | }; | 1509 | // }; |
| 1521 | | 1510 | |
| 1522 | const a = A{}; | 1511 | // const a = A{}; |
| 1523 | const b = B{ .a = a, .c = 0 }; | 1512 | // const b = B{ .a = a, .c = 0 }; |
| 1524 | | 1513 | |
| 1525 | try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b}); | 1514 | // try testFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b}); |
| 1526 | } | 1515 | // } |
| 1527 | | 1516 | |
| 1528 | test "bytes.hex" { | 1517 | // test "bytes.hex" { |
| 1529 | const some_bytes = "\xCA\xFE\xBA\xBE"; | 1518 | // const some_bytes = "\xCA\xFE\xBA\xBE"; |
| 1530 | try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes}); | 1519 | // try testFmt("lowercase: cafebabe\n", "lowercase: {x}\n", .{some_bytes}); |
| 1531 | try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes}); | 1520 | // try testFmt("uppercase: CAFEBABE\n", "uppercase: {X}\n", .{some_bytes}); |
| 1532 | //Test Slices | 1521 | // //Test Slices |
| 1533 | try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]}); | 1522 | // try testFmt("uppercase: CAFE\n", "uppercase: {X}\n", .{some_bytes[0..2]}); |
| 1534 | try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]}); | 1523 | // try testFmt("lowercase: babe\n", "lowercase: {x}\n", .{some_bytes[2..]}); |
| 1535 | const bytes_with_zeros = "\x00\x0E\xBA\xBE"; | 1524 | // const bytes_with_zeros = "\x00\x0E\xBA\xBE"; |
| 1536 | try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros}); | 1525 | // try testFmt("lowercase: 000ebabe\n", "lowercase: {x}\n", .{bytes_with_zeros}); |
| 1537 | } | 1526 | // } |
| 1538 | | 1527 | |
| 1539 | fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void { | 1528 | // fn testFmt(expected: []const u8, comptime template: []const u8, args: var) !void { |
| 1540 | var buf: [100]u8 = undefined; | 1529 | // var buf: [100]u8 = undefined; |
| 1541 | const result = try bufPrint(buf[0..], template, args); | 1530 | // const result = try bufPrint(buf[0..], template, args); |
| 1542 | if (mem.eql(u8, result, expected)) return; | 1531 | // if (mem.eql(u8, result, expected)) return; |
| 1543 | | 1532 | |
| 1544 | std.debug.warn("\n====== expected this output: =========\n", .{}); | 1533 | // std.debug.warn("\n====== expected this output: =========\n", .{}); |
| 1545 | std.debug.warn("{}", .{expected}); | 1534 | // std.debug.warn("{}", .{expected}); |
| 1546 | std.debug.warn("\n======== instead found this: =========\n", .{}); | 1535 | // std.debug.warn("\n======== instead found this: =========\n", .{}); |
| 1547 | std.debug.warn("{}", .{result}); | 1536 | // std.debug.warn("{}", .{result}); |
| 1548 | std.debug.warn("\n======================================\n", .{}); | 1537 | // std.debug.warn("\n======================================\n", .{}); |
| 1549 | return error.TestFailed; | 1538 | // return error.TestFailed; |
| 1550 | } | 1539 | // } |
| 1551 | | 1540 | |
| 1552 | pub fn trim(buf: []const u8) []const u8 { | 1541 | // pub fn trim(buf: []const u8) []const u8 { |
| 1553 | var start: usize = 0; | 1542 | // var start: usize = 0; |
| 1554 | while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {} | 1543 | // while (start < buf.len and isWhiteSpace(buf[start])) : (start += 1) {} |
| 1555 | | 1544 | |
| 1556 | var end: usize = buf.len; | 1545 | // var end: usize = buf.len; |
| 1557 | while (true) { | 1546 | // while (true) { |
| 1558 | if (end > start) { | 1547 | // if (end > start) { |
| 1559 | const new_end = end - 1; | 1548 | // const new_end = end - 1; |
| 1560 | if (isWhiteSpace(buf[new_end])) { | 1549 | // if (isWhiteSpace(buf[new_end])) { |
| 1561 | end = new_end; | 1550 | // end = new_end; |
| 1562 | continue; | 1551 | // continue; |
| 1563 | } | 1552 | // } |
| 1564 | } | 1553 | // } |
| 1565 | break; | 1554 | // break; |
| 1566 | } | 1555 | // } |
| 1567 | return buf[start..end]; | 1556 | // return buf[start..end]; |
| 1568 | } | 1557 | // } |
| 1569 | | 1558 | |
| 1570 | test "trim" { | 1559 | // test "trim" { |
| 1571 | std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t"))); | 1560 | // std.testing.expect(mem.eql(u8, "abc", trim("\n abc \t"))); |
| 1572 | std.testing.expect(mem.eql(u8, "", trim(" "))); | 1561 | // std.testing.expect(mem.eql(u8, "", trim(" "))); |
| 1573 | std.testing.expect(mem.eql(u8, "", trim(""))); | 1562 | // std.testing.expect(mem.eql(u8, "", trim(""))); |
| 1574 | std.testing.expect(mem.eql(u8, "abc", trim(" abc"))); | 1563 | // std.testing.expect(mem.eql(u8, "abc", trim(" abc"))); |
| 1575 | std.testing.expect(mem.eql(u8, "abc", trim("abc "))); | 1564 | // std.testing.expect(mem.eql(u8, "abc", trim("abc "))); |
| 1576 | } | 1565 | // } |
| 1577 | | 1566 | |
| 1578 | pub fn isWhiteSpace(byte: u8) bool { | 1567 | // pub fn isWhiteSpace(byte: u8) bool { |
| 1579 | return switch (byte) { | 1568 | // return switch (byte) { |
| 1580 | ' ', '\t', '\n', '\r' => true, | 1569 | // ' ', '\t', '\n', '\r' => true, |
| 1581 | else => false, | 1570 | // else => false, |
| 1582 | }; | 1571 | // }; |
| 1583 | } | 1572 | // } |
| 1584 | | 1573 | |
| 1585 | pub fn hexToBytes(out: []u8, input: []const u8) !void { | 1574 | // pub fn hexToBytes(out: []u8, input: []const u8) !void { |
| 1586 | if (out.len * 2 < input.len) | 1575 | // if (out.len * 2 < input.len) |
| 1587 | return error.InvalidLength; | 1576 | // return error.InvalidLength; |
| 1588 | | 1577 | |
| 1589 | var in_i: usize = 0; | 1578 | // var in_i: usize = 0; |
| 1590 | while (in_i != input.len) : (in_i += 2) { | 1579 | // while (in_i != input.len) : (in_i += 2) { |
| 1591 | const hi = try charToDigit(input[in_i], 16); | 1580 | // const hi = try charToDigit(input[in_i], 16); |
| 1592 | const lo = try charToDigit(input[in_i + 1], 16); | 1581 | // const lo = try charToDigit(input[in_i + 1], 16); |
| 1593 | out[in_i / 2] = (hi << 4) | lo; | 1582 | // out[in_i / 2] = (hi << 4) | lo; |
| 1594 | } | 1583 | // } |
| 1595 | } | 1584 | // } |
| 1596 | | 1585 | |
| 1597 | test "hexToBytes" { | 1586 | // test "hexToBytes" { |
| 1598 | const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706"; | 1587 | // const test_hex_str = "909A312BB12ED1F819B3521AC4C1E896F2160507FFC1C8381E3B07BB16BD1706"; |
| 1599 | var pb: [32]u8 = undefined; | 1588 | // var pb: [32]u8 = undefined; |
| 1600 | try hexToBytes(pb[0..], test_hex_str); | 1589 | // try hexToBytes(pb[0..], test_hex_str); |
| 1601 | try testFmt(test_hex_str, "{X}", .{pb}); | 1590 | // try testFmt(test_hex_str, "{X}", .{pb}); |
| 1602 | } | 1591 | // } |
| 1603 | | 1592 | |
| 1604 | test "formatIntValue with comptime_int" { | 1593 | // test "formatIntValue with comptime_int" { |
| 1605 | const value: comptime_int = 123456789123456789; | 1594 | // const value: comptime_int = 123456789123456789; |
| 1606 | | 1595 | |
| 1607 | var buf = std.ArrayList(u8).init(std.testing.allocator); | 1596 | // var buf = std.ArrayList(u8).init(std.testing.allocator); |
| 1608 | defer buf.deinit(); | 1597 | // defer buf.deinit(); |
| 1609 | try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice); | 1598 | // try formatIntValue(value, "", FormatOptions{}, &buf, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice); |
| 1610 | std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789")); | 1599 | // std.testing.expect(mem.eql(u8, buf.toSliceConst(), "123456789123456789")); |
| 1611 | } | 1600 | // } |
| 1612 | | 1601 | |
| 1613 | test "formatType max_depth" { | 1602 | // test "formatType max_depth" { |
| 1614 | const Vec2 = struct { | 1603 | // const Vec2 = struct { |
| 1615 | const SelfType = @This(); | 1604 | // const SelfType = @This(); |
| 1616 | x: f32, | 1605 | // x: f32, |
| 1617 | y: f32, | 1606 | // y: f32, |
| 1618 | | 1607 | |
| 1619 | pub fn format( | 1608 | // pub fn format( |
| 1620 | self: SelfType, | 1609 | // self: SelfType, |
| 1621 | comptime fmt: []const u8, | 1610 | // comptime fmt: []const u8, |
| 1622 | options: FormatOptions, | 1611 | // options: FormatOptions, |
| 1623 | context: var, | 1612 | // context: var, |
| 1624 | comptime Errors: type, | 1613 | // comptime Errors: type, |
| 1625 | comptime output: fn (@TypeOf(context), []const u8) !void, | 1614 | // comptime output: fn (@TypeOf(context), []const u8) !void, |
| 1626 | ) !void { | 1615 | // ) !void { |
| 1627 | if (fmt.len == 0) { | 1616 | // if (fmt.len == 0) { |
| 1628 | return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); | 1617 | // return std.fmtstream.format(out_stream, "({d:.3},{d:.3})", .{ self.x, self.y }); |
| 1629 | } else { | 1618 | // } else { |
| 1630 | @compileError("Unknown format string: '" ++ fmt ++ "'"); | 1619 | // @compileError("Unknown format string: '" ++ fmt ++ "'"); |
| 1631 | } | 1620 | // } |
| 1632 | } | 1621 | // } |
| 1633 | }; | 1622 | // }; |
| 1634 | const E = enum { | 1623 | // const E = enum { |
| 1635 | One, | 1624 | // One, |
| 1636 | Two, | 1625 | // Two, |
| 1637 | Three, | 1626 | // Three, |
| 1638 | }; | 1627 | // }; |
| 1639 | const TU = union(enum) { | 1628 | // const TU = union(enum) { |
| 1640 | const SelfType = @This(); | 1629 | // const SelfType = @This(); |
| 1641 | float: f32, | 1630 | // float: f32, |
| 1642 | int: u32, | 1631 | // int: u32, |
| 1643 | ptr: ?*SelfType, | 1632 | // ptr: ?*SelfType, |
| 1644 | }; | 1633 | // }; |
| 1645 | const S = struct { | 1634 | // const S = struct { |
| 1646 | const SelfType = @This(); | 1635 | // const SelfType = @This(); |
| 1647 | a: ?*SelfType, | 1636 | // a: ?*SelfType, |
| 1648 | tu: TU, | 1637 | // tu: TU, |
| 1649 | e: E, | 1638 | // e: E, |
| 1650 | vec: Vec2, | 1639 | // vec: Vec2, |
| 1651 | }; | 1640 | // }; |
| 1652 | | 1641 | |
| 1653 | var inst = S{ | 1642 | // var inst = S{ |
| 1654 | .a = null, | 1643 | // .a = null, |
| 1655 | .tu = TU{ .ptr = null }, | 1644 | // .tu = TU{ .ptr = null }, |
| 1656 | .e = E.Two, | 1645 | // .e = E.Two, |
| 1657 | .vec = Vec2{ .x = 10.2, .y = 2.22 }, | 1646 | // .vec = Vec2{ .x = 10.2, .y = 2.22 }, |
| 1658 | }; | 1647 | // }; |
| 1659 | inst.a = &inst; | 1648 | // inst.a = &inst; |
| 1660 | inst.tu.ptr = &inst.tu; | 1649 | // inst.tu.ptr = &inst.tu; |
| 1661 | | 1650 | |
| 1662 | var buf0 = std.ArrayList(u8).init(std.testing.allocator); | 1651 | // var buf0 = std.ArrayList(u8).init(std.testing.allocator); |
| 1663 | defer buf0.deinit(); | 1652 | // defer buf0.deinit(); |
| 1664 | try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0); | 1653 | // try formatType(inst, "", FormatOptions{}, &buf0, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 0); |
| 1665 | std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }")); | 1654 | // std.testing.expect(mem.eql(u8, buf0.toSlice(), "S{ ... }")); |
| 1666 | | 1655 | |
| 1667 | var buf1 = std.ArrayList(u8).init(std.testing.allocator); | 1656 | // var buf1 = std.ArrayList(u8).init(std.testing.allocator); |
| 1668 | defer buf1.deinit(); | 1657 | // defer buf1.deinit(); |
| 1669 | try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1); | 1658 | // try formatType(inst, "", FormatOptions{}, &buf1, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 1); |
| 1670 | std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); | 1659 | // std.testing.expect(mem.eql(u8, buf1.toSlice(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); |
| 1671 | | 1660 | |
| 1672 | var buf2 = std.ArrayList(u8).init(std.testing.allocator); | 1661 | // var buf2 = std.ArrayList(u8).init(std.testing.allocator); |
| 1673 | defer buf2.deinit(); | 1662 | // defer buf2.deinit(); |
| 1674 | try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2); | 1663 | // try formatType(inst, "", FormatOptions{}, &buf2, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 2); |
| 1675 | 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) }")); | 1664 | // 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) }")); |
| 1676 | | 1665 | |
| 1677 | var buf3 = std.ArrayList(u8).init(std.testing.allocator); | 1666 | // var buf3 = std.ArrayList(u8).init(std.testing.allocator); |
| 1678 | defer buf3.deinit(); | 1667 | // defer buf3.deinit(); |
| 1679 | try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3); | 1668 | // try formatType(inst, "", FormatOptions{}, &buf3, @TypeOf(std.ArrayList(u8).appendSlice).ReturnType.ErrorSet, std.ArrayList(u8).appendSlice, 3); |
| 1680 | 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) }")); | 1669 | // 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) }")); |
| 1681 | } | 1670 | // } |
| 1682 | | 1671 | |
| 1683 | test "positional" { | 1672 | // test "positional" { |
| 1684 | try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); | 1673 | // try testFmt("2 1 0", "{2} {1} {0}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); |
| 1685 | try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); | 1674 | // try testFmt("2 1 0", "{2} {1} {}", .{ @as(usize, 0), @as(usize, 1), @as(usize, 2) }); |
| 1686 | try testFmt("0 0", "{0} {0}", .{@as(usize, 0)}); | 1675 | // try testFmt("0 0", "{0} {0}", .{@as(usize, 0)}); |
| 1687 | try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) }); | 1676 | // try testFmt("0 1", "{} {1}", .{ @as(usize, 0), @as(usize, 1) }); |
| 1688 | try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) }); | 1677 | // try testFmt("1 0 0 1", "{1} {} {0} {}", .{ @as(usize, 0), @as(usize, 1) }); |
| 1689 | } | 1678 | // } |
| 1690 | | 1679 | |
| 1691 | test "positional with specifier" { | 1680 | // test "positional with specifier" { |
| 1692 | try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)}); | 1681 | // try testFmt("10.0", "{0d:.1}", .{@as(f64, 9.999)}); |
| 1693 | } | 1682 | // } |
| 1694 | | 1683 | |
| 1695 | test "positional/alignment/width/precision" { | 1684 | // test "positional/alignment/width/precision" { |
| 1696 | try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)}); | 1685 | // try testFmt("10.0", "{0d: >3.1}", .{@as(f64, 9.999)}); |
| 1697 | } | 1686 | // } |
| 1698 | | 1687 | |
| 1699 | test "vector" { | 1688 | // test "vector" { |
| 1700 | // https://github.com/ziglang/zig/issues/3317 | 1689 | // // https://github.com/ziglang/zig/issues/3317 |
| 1701 | if (builtin.arch == .mipsel) return error.SkipZigTest; | 1690 | // if (builtin.arch == .mipsel) return error.SkipZigTest; |
| 1702 | | 1691 | |
| 1703 | const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false }; | 1692 | // const vbool: @Vector(4, bool) = [_]bool{ true, false, true, false }; |
| 1704 | const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 }; | 1693 | // const vi64: @Vector(4, i64) = [_]i64{ -2, -1, 0, 1 }; |
| 1705 | const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 }; | 1694 | // const vu64: @Vector(4, u64) = [_]u64{ 1000, 2000, 3000, 4000 }; |
| 1706 | | 1695 | |
| 1707 | try testFmt("{ true, false, true, false }", "{}", .{vbool}); | 1696 | // try testFmt("{ true, false, true, false }", "{}", .{vbool}); |
| 1708 | try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64}); | 1697 | // try testFmt("{ -2, -1, 0, 1 }", "{}", .{vi64}); |
| 1709 | try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64}); | 1698 | // try testFmt("{ - 2, - 1, + 0, + 1 }", "{d:5}", .{vi64}); |
| 1710 | try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64}); | 1699 | // try testFmt("{ 1000, 2000, 3000, 4000 }", "{}", .{vu64}); |
| 1711 | try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64}); | 1700 | // try testFmt("{ 3e8, 7d0, bb8, fa0 }", "{x}", .{vu64}); |
| 1712 | try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64}); | 1701 | // try testFmt("{ 1kB, 2kB, 3kB, 4kB }", "{B}", .{vu64}); |
| 1713 | try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64}); | 1702 | // try testFmt("{ 1000B, 1.953125KiB, 2.9296875KiB, 3.90625KiB }", "{Bi}", .{vu64}); |
| 1714 | } | 1703 | // } |
| 1715 | | 1704 | |
| 1716 | test "enum-literal" { | 1705 | // test "enum-literal" { |
| 1717 | try testFmt(".hello_world", "{}", .{.hello_world}); | 1706 | // try testFmt(".hello_world", "{}", .{.hello_world}); |
| 1718 | } | 1707 | // } |