| author | |
| committer | |
| log | 1d763c8b29360a5f3b52747231876b54db1c7ba0 |
| tree | c8092a1dc9675797310567ee61c9f20e0dfc906a |
| parent | 7eae26d60895dc62fa62f6562a4eeecb8685aae5 |
for structs, enums, and unions.
auto untagged unions are no longer printed as pointers; instead they are
printed as "{ ... }".
extern and packed untagged unions have each field printed, similar to
what gdb does.
also fix bugs in delimiter based reading4 files changed, 177 insertions(+), 128 deletions(-)
lib/std/fmt.zig+26-31| ... | ... | @@ -996,7 +996,7 @@ test "slice" { |
| 996 | 996 | x: u8, |
| 997 | 997 | }; |
| 998 | 998 | const struct_slice: []const S1 = &[_]S1{ S1{ .x = 8 }, S1{ .x = 42 } }; |
| 999 | try expectFmt("slice: { fmt.test.slice.S1{ .x = 8 }, fmt.test.slice.S1{ .x = 42 } }", "slice: {any}", .{struct_slice}); | |
| 999 | try expectFmt("slice: { .{ .x = 8 }, .{ .x = 42 } }", "slice: {any}", .{struct_slice}); | |
| 1000 | 1000 | } |
| 1001 | 1001 | { |
| 1002 | 1002 | const S2 = struct { |
| ... | ... | @@ -1007,7 +1007,7 @@ test "slice" { |
| 1007 | 1007 | } |
| 1008 | 1008 | }; |
| 1009 | 1009 | const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } }; |
| 1010 | try expectFmt("slice: { fmt.test.slice.S2{ .x = 8 }, fmt.test.slice.S2{ .x = 42 } }", "slice: {any}", .{struct_slice}); | |
| 1010 | try expectFmt("slice: { .{ .x = 8 }, .{ .x = 42 } }", "slice: {any}", .{struct_slice}); | |
| 1011 | 1011 | } |
| 1012 | 1012 | } |
| 1013 | 1013 | |
| ... | ... | @@ -1047,8 +1047,8 @@ test "struct" { |
| 1047 | 1047 | field: u8, |
| 1048 | 1048 | }; |
| 1049 | 1049 | const value = Struct{ .field = 42 }; |
| 1050 | try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{value}); | |
| 1051 | try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{&value}); | |
| 1050 | try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{value}); | |
| 1051 | try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{&value}); | |
| 1052 | 1052 | } |
| 1053 | 1053 | { |
| 1054 | 1054 | const Struct = struct { |
| ... | ... | @@ -1056,7 +1056,7 @@ test "struct" { |
| 1056 | 1056 | b: u1, |
| 1057 | 1057 | }; |
| 1058 | 1058 | const value = Struct{ .a = 0, .b = 1 }; |
| 1059 | try expectFmt("struct: fmt.test.struct.Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); | |
| 1059 | try expectFmt("struct: .{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); | |
| 1060 | 1060 | } |
| 1061 | 1061 | |
| 1062 | 1062 | const S = struct { |
| ... | ... | @@ -1069,11 +1069,11 @@ test "struct" { |
| 1069 | 1069 | .b = error.Unused, |
| 1070 | 1070 | }; |
| 1071 | 1071 | |
| 1072 | try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst}); | |
| 1072 | try expectFmt(".{ .a = 456, .b = error.Unused }", "{}", .{inst}); | |
| 1073 | 1073 | // Tuples |
| 1074 | try expectFmt("{ }", "{}", .{.{}}); | |
| 1075 | try expectFmt("{ -1 }", "{}", .{.{-1}}); | |
| 1076 | try expectFmt("{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }}); | |
| 1074 | try expectFmt(".{ }", "{}", .{.{}}); | |
| 1075 | try expectFmt(".{ -1 }", "{}", .{.{-1}}); | |
| 1076 | try expectFmt(".{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }}); | |
| 1077 | 1077 | } |
| 1078 | 1078 | |
| 1079 | 1079 | test "enum" { |
| ... | ... | @@ -1082,15 +1082,15 @@ test "enum" { |
| 1082 | 1082 | Two, |
| 1083 | 1083 | }; |
| 1084 | 1084 | const value = Enum.Two; |
| 1085 | try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{value}); | |
| 1086 | try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{&value}); | |
| 1087 | try expectFmt("enum: fmt.test.enum.Enum.One\n", "enum: {}\n", .{Enum.One}); | |
| 1088 | try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); | |
| 1085 | try expectFmt("enum: .Two\n", "enum: {}\n", .{value}); | |
| 1086 | try expectFmt("enum: .Two\n", "enum: {}\n", .{&value}); | |
| 1087 | try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One}); | |
| 1088 | try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two}); | |
| 1089 | 1089 | |
| 1090 | 1090 | // test very large enum to verify ct branch quota is large enough |
| 1091 | 1091 | // TODO: https://github.com/ziglang/zig/issues/15609 |
| 1092 | 1092 | if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) { |
| 1093 | try expectFmt("enum: os.windows.win32error.Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION}); | |
| 1093 | try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION}); | |
| 1094 | 1094 | } |
| 1095 | 1095 | |
| 1096 | 1096 | const E = enum { |
| ... | ... | @@ -1101,7 +1101,7 @@ test "enum" { |
| 1101 | 1101 | |
| 1102 | 1102 | const inst = E.Two; |
| 1103 | 1103 | |
| 1104 | try expectFmt("fmt.test.enum.E.Two", "{}", .{inst}); | |
| 1104 | try expectFmt(".Two", "{}", .{inst}); | |
| 1105 | 1105 | } |
| 1106 | 1106 | |
| 1107 | 1107 | test "non-exhaustive enum" { |
| ... | ... | @@ -1110,9 +1110,9 @@ test "non-exhaustive enum" { |
| 1110 | 1110 | Two = 0xbeef, |
| 1111 | 1111 | _, |
| 1112 | 1112 | }; |
| 1113 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One}); | |
| 1114 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); | |
| 1115 | try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))}); | |
| 1113 | try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One}); | |
| 1114 | try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two}); | |
| 1115 | try expectFmt("enum: @enumFromInt(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))}); | |
| 1116 | 1116 | try expectFmt("enum: f\n", "enum: {x}\n", .{Enum.One}); |
| 1117 | 1117 | try expectFmt("enum: beef\n", "enum: {x}\n", .{Enum.Two}); |
| 1118 | 1118 | try expectFmt("enum: BEEF\n", "enum: {X}\n", .{Enum.Two}); |
| ... | ... | @@ -1291,18 +1291,13 @@ test "union" { |
| 1291 | 1291 | int: u32, |
| 1292 | 1292 | }; |
| 1293 | 1293 | |
| 1294 | const tu_inst = TU{ .int = 123 }; | |
| 1295 | const uu_inst = UU{ .int = 456 }; | |
| 1296 | const eu_inst = EU{ .float = 321.123 }; | |
| 1294 | const tu_inst: TU = .{ .int = 123 }; | |
| 1295 | const uu_inst: UU = .{ .int = 456 }; | |
| 1296 | const eu_inst: EU = .{ .float = 321.123 }; | |
| 1297 | 1297 | |
| 1298 | try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst}); | |
| 1299 | ||
| 1300 | var buf: [100]u8 = undefined; | |
| 1301 | const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); | |
| 1302 | try std.testing.expectEqualStrings("fmt.test.union.UU@", uu_result[0..18]); | |
| 1303 | ||
| 1304 | const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); | |
| 1305 | try std.testing.expectEqualStrings("fmt.test.union.EU@", eu_result[0..18]); | |
| 1298 | try expectFmt(".{ .int = 123 }", "{}", .{tu_inst}); | |
| 1299 | try expectFmt(".{ ... }", "{}", .{uu_inst}); | |
| 1300 | try expectFmt(".{ .float = 321.123, .int = 1134596030 }", "{}", .{eu_inst}); | |
| 1306 | 1301 | } |
| 1307 | 1302 | |
| 1308 | 1303 | test "struct.self-referential" { |
| ... | ... | @@ -1316,7 +1311,7 @@ test "struct.self-referential" { |
| 1316 | 1311 | }; |
| 1317 | 1312 | inst.a = &inst; |
| 1318 | 1313 | |
| 1319 | try expectFmt("fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ ... } } } }", "{}", .{inst}); | |
| 1314 | try expectFmt(".{ .a = .{ .a = .{ .a = .{ ... } } } }", "{}", .{inst}); | |
| 1320 | 1315 | } |
| 1321 | 1316 | |
| 1322 | 1317 | test "struct.zero-size" { |
| ... | ... | @@ -1331,7 +1326,7 @@ test "struct.zero-size" { |
| 1331 | 1326 | const a = A{}; |
| 1332 | 1327 | const b = B{ .a = a, .c = 0 }; |
| 1333 | 1328 | |
| 1334 | try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b}); | |
| 1329 | try expectFmt(".{ .a = .{ }, .c = 0 }", "{}", .{b}); | |
| 1335 | 1330 | } |
| 1336 | 1331 | |
| 1337 | 1332 | /// Encodes a sequence of bytes as hexadecimal digits. |
lib/std/io/Reader.zig+108-38| ... | ... | @@ -36,7 +36,10 @@ pub const VTable = struct { |
| 36 | 36 | /// sizes combined with short reads (returning a value less than `limit`) |
| 37 | 37 | /// in order to minimize complexity. |
| 38 | 38 | /// |
| 39 | /// This function is always called when `buffer` is empty. | |
| 39 | /// Although this function is usually called when `buffer` is empty, it is | |
| 40 | /// also called when it needs to be filled more due to the API user | |
| 41 | /// requesting contiguous memory. In either case, the existing buffer data | |
| 42 | /// should be ignored; new data written to `w`. | |
| 40 | 43 | stream: *const fn (r: *Reader, w: *Writer, limit: Limit) StreamError!usize, |
| 41 | 44 | |
| 42 | 45 | /// Consumes bytes from the internally tracked stream position without |
| ... | ... | @@ -194,7 +197,7 @@ pub fn streamRemaining(r: *Reader, w: *Writer) StreamRemainingError!usize { |
| 194 | 197 | /// Consumes the stream until the end, ignoring all the data, returning the |
| 195 | 198 | /// number of bytes discarded. |
| 196 | 199 | pub fn discardRemaining(r: *Reader) ShortError!usize { |
| 197 | var offset: usize = r.end; | |
| 200 | var offset: usize = r.end - r.seek; | |
| 198 | 201 | r.seek = 0; |
| 199 | 202 | r.end = 0; |
| 200 | 203 | while (true) { |
| ... | ... | @@ -693,6 +696,17 @@ pub fn takeSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel |
| 693 | 696 | return result; |
| 694 | 697 | } |
| 695 | 698 | |
| 699 | /// Returns a slice of the next bytes of buffered data from the stream until | |
| 700 | /// `sentinel` is found, without advancing the seek position. | |
| 701 | /// | |
| 702 | /// Returned slice has a sentinel; end of stream does not count as a delimiter. | |
| 703 | /// | |
| 704 | /// Invalidates previously returned values from `peek`. | |
| 705 | /// | |
| 706 | /// See also: | |
| 707 | /// * `takeSentinel` | |
| 708 | /// * `peekDelimiterExclusive` | |
| 709 | /// * `peekDelimiterInclusive` | |
| 696 | 710 | pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 { |
| 697 | 711 | const result = try r.peekDelimiterInclusive(sentinel); |
| 698 | 712 | return result[0 .. result.len - 1 :sentinel]; |
| ... | ... | @@ -733,27 +747,37 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 733 | 747 | @branchHint(.likely); |
| 734 | 748 | return buffer[seek .. end + 1]; |
| 735 | 749 | } |
| 736 | if (seek > 0) { | |
| 737 | const remainder = buffer[seek..]; | |
| 738 | @memmove(buffer[0..remainder.len], remainder); | |
| 739 | r.end = remainder.len; | |
| 740 | r.seek = 0; | |
| 750 | while (r.buffer.len - r.end != 0) { | |
| 751 | const end_cap = r.buffer[r.end..]; | |
| 752 | var writer: Writer = .fixed(end_cap); | |
| 753 | const n = r.vtable.stream(r, &writer, .limited(end_cap.len)) catch |err| switch (err) { | |
| 754 | error.WriteFailed => unreachable, | |
| 755 | else => |e| return e, | |
| 756 | }; | |
| 757 | r.end += n; | |
| 758 | if (std.mem.indexOfScalarPos(u8, end_cap[0..n], 0, delimiter)) |end| { | |
| 759 | return r.buffer[seek .. r.end - n + end + 1]; | |
| 760 | } | |
| 741 | 761 | } |
| 742 | var writer: Writer = .{ | |
| 743 | .buffer = r.buffer, | |
| 744 | .vtable = &.{ .drain = Writer.fixedDrain }, | |
| 745 | }; | |
| 746 | while (r.end < r.buffer.len) { | |
| 747 | writer.end = r.end; | |
| 748 | const n = r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) { | |
| 762 | var i: usize = 0; | |
| 763 | while (seek - i != 0) { | |
| 764 | const begin_cap = r.buffer[i..seek]; | |
| 765 | var writer: Writer = .fixed(begin_cap); | |
| 766 | const n = r.vtable.stream(r, &writer, .limited(begin_cap.len)) catch |err| switch (err) { | |
| 749 | 767 | error.WriteFailed => unreachable, |
| 750 | 768 | else => |e| return e, |
| 751 | 769 | }; |
| 752 | const prev_end = r.end; | |
| 753 | r.end = prev_end + n; | |
| 754 | if (std.mem.indexOfScalarPos(u8, r.buffer[0..r.end], prev_end, delimiter)) |end| { | |
| 755 | return r.buffer[0 .. end + 1]; | |
| 770 | i += n; | |
| 771 | if (std.mem.indexOfScalarPos(u8, r.buffer[0..seek], i, delimiter)) |end| { | |
| 772 | std.mem.rotate(u8, r.buffer, seek); | |
| 773 | r.seek = 0; | |
| 774 | r.end += i; | |
| 775 | return r.buffer[0 .. seek + end + 1]; | |
| 756 | 776 | } |
| 777 | } else if (i != 0) { | |
| 778 | std.mem.rotate(u8, r.buffer, seek); | |
| 779 | r.seek = 0; | |
| 780 | r.end += i; | |
| 757 | 781 | } |
| 758 | 782 | return error.StreamTooLong; |
| 759 | 783 | } |
| ... | ... | @@ -778,9 +802,10 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 778 | 802 | pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 779 | 803 | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { |
| 780 | 804 | error.EndOfStream => { |
| 781 | if (r.end == 0) return error.EndOfStream; | |
| 782 | r.toss(r.end); | |
| 783 | return r.buffer[0..r.end]; | |
| 805 | const remaining = r.buffer[r.seek..r.end]; | |
| 806 | if (remaining.len == 0) return error.EndOfStream; | |
| 807 | r.toss(remaining.len); | |
| 808 | return remaining; | |
| 784 | 809 | }, |
| 785 | 810 | else => |e| return e, |
| 786 | 811 | }; |
| ... | ... | @@ -808,8 +833,10 @@ pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 808 | 833 | pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { |
| 809 | 834 | const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { |
| 810 | 835 | error.EndOfStream => { |
| 811 | if (r.end == 0) return error.EndOfStream; | |
| 812 | return r.buffer[0..r.end]; | |
| 836 | const remaining = r.buffer[r.seek..r.end]; | |
| 837 | if (remaining.len == 0) return error.EndOfStream; | |
| 838 | r.toss(remaining.len); | |
| 839 | return remaining; | |
| 813 | 840 | }, |
| 814 | 841 | else => |e| return e, |
| 815 | 842 | }; |
| ... | ... | @@ -1219,27 +1246,38 @@ test fixed { |
| 1219 | 1246 | } |
| 1220 | 1247 | |
| 1221 | 1248 | test peek { |
| 1222 | return error.Unimplemented; | |
| 1249 | var r: Reader = .fixed("abc"); | |
| 1250 | try testing.expectEqualStrings("ab", try r.peek(2)); | |
| 1251 | try testing.expectEqualStrings("a", try r.peek(1)); | |
| 1223 | 1252 | } |
| 1224 | 1253 | |
| 1225 | 1254 | test peekGreedy { |
| 1226 | return error.Unimplemented; | |
| 1255 | var r: Reader = .fixed("abc"); | |
| 1256 | try testing.expectEqualStrings("abc", try r.peekGreedy(1)); | |
| 1227 | 1257 | } |
| 1228 | 1258 | |
| 1229 | 1259 | test toss { |
| 1230 | return error.Unimplemented; | |
| 1260 | var r: Reader = .fixed("abc"); | |
| 1261 | r.toss(1); | |
| 1262 | try testing.expectEqualStrings("bc", r.buffered()); | |
| 1231 | 1263 | } |
| 1232 | 1264 | |
| 1233 | 1265 | test take { |
| 1234 | return error.Unimplemented; | |
| 1266 | var r: Reader = .fixed("abc"); | |
| 1267 | try testing.expectEqualStrings("ab", try r.take(2)); | |
| 1268 | try testing.expectEqualStrings("c", try r.take(1)); | |
| 1235 | 1269 | } |
| 1236 | 1270 | |
| 1237 | 1271 | test takeArray { |
| 1238 | return error.Unimplemented; | |
| 1272 | var r: Reader = .fixed("abc"); | |
| 1273 | try testing.expectEqualStrings("ab", try r.takeArray(2)); | |
| 1274 | try testing.expectEqualStrings("c", try r.takeArray(1)); | |
| 1239 | 1275 | } |
| 1240 | 1276 | |
| 1241 | 1277 | test peekArray { |
| 1242 | return error.Unimplemented; | |
| 1278 | var r: Reader = .fixed("abc"); | |
| 1279 | try testing.expectEqualStrings("ab", try r.peekArray(2)); | |
| 1280 | try testing.expectEqualStrings("a", try r.peekArray(1)); | |
| 1243 | 1281 | } |
| 1244 | 1282 | |
| 1245 | 1283 | test discardAll { |
| ... | ... | @@ -1251,35 +1289,63 @@ test discardAll { |
| 1251 | 1289 | } |
| 1252 | 1290 | |
| 1253 | 1291 | test discardRemaining { |
| 1254 | return error.Unimplemented; | |
| 1292 | var r: Reader = .fixed("foobar"); | |
| 1293 | r.toss(1); | |
| 1294 | try testing.expectEqual(5, try r.discardRemaining()); | |
| 1295 | try testing.expectEqual(0, try r.discardRemaining()); | |
| 1255 | 1296 | } |
| 1256 | 1297 | |
| 1257 | 1298 | test stream { |
| 1258 | return error.Unimplemented; | |
| 1299 | var out_buffer: [10]u8 = undefined; | |
| 1300 | var r: Reader = .fixed("foobar"); | |
| 1301 | var w: Writer = .fixed(&out_buffer); | |
| 1302 | // Short streams are possible with this function but not with fixed. | |
| 1303 | try testing.expectEqual(2, try r.stream(&w, .limited(2))); | |
| 1304 | try testing.expectEqualStrings("fo", w.buffered()); | |
| 1305 | try testing.expectEqual(4, try r.stream(&w, .unlimited)); | |
| 1306 | try testing.expectEqualStrings("foobar", w.buffered()); | |
| 1259 | 1307 | } |
| 1260 | 1308 | |
| 1261 | 1309 | test takeSentinel { |
| 1262 | return error.Unimplemented; | |
| 1310 | var r: Reader = .fixed("ab\nc"); | |
| 1311 | try testing.expectEqualStrings("ab", try r.takeSentinel('\n')); | |
| 1312 | try testing.expectError(error.EndOfStream, r.takeSentinel('\n')); | |
| 1313 | try testing.expectEqualStrings("c", try r.peek(1)); | |
| 1263 | 1314 | } |
| 1264 | 1315 | |
| 1265 | 1316 | test peekSentinel { |
| 1266 | return error.Unimplemented; | |
| 1317 | var r: Reader = .fixed("ab\nc"); | |
| 1318 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); | |
| 1319 | try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); | |
| 1267 | 1320 | } |
| 1268 | 1321 | |
| 1269 | 1322 | test takeDelimiterInclusive { |
| 1270 | return error.Unimplemented; | |
| 1323 | var r: Reader = .fixed("ab\nc"); | |
| 1324 | try testing.expectEqualStrings("ab\n", try r.takeDelimiterInclusive('\n')); | |
| 1325 | try testing.expectError(error.EndOfStream, r.takeDelimiterInclusive('\n')); | |
| 1271 | 1326 | } |
| 1272 | 1327 | |
| 1273 | 1328 | test peekDelimiterInclusive { |
| 1274 | return error.Unimplemented; | |
| 1329 | var r: Reader = .fixed("ab\nc"); | |
| 1330 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); | |
| 1331 | try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); | |
| 1332 | r.toss(3); | |
| 1333 | try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); | |
| 1275 | 1334 | } |
| 1276 | 1335 | |
| 1277 | 1336 | test takeDelimiterExclusive { |
| 1278 | return error.Unimplemented; | |
| 1337 | var r: Reader = .fixed("ab\nc"); | |
| 1338 | try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); | |
| 1339 | try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); | |
| 1340 | try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); | |
| 1279 | 1341 | } |
| 1280 | 1342 | |
| 1281 | 1343 | test peekDelimiterExclusive { |
| 1282 | return error.Unimplemented; | |
| 1344 | var r: Reader = .fixed("ab\nc"); | |
| 1345 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); | |
| 1346 | try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); | |
| 1347 | r.toss(3); | |
| 1348 | try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); | |
| 1283 | 1349 | } |
| 1284 | 1350 | |
| 1285 | 1351 | test readDelimiter { |
| ... | ... | @@ -1339,7 +1405,11 @@ test peekStructEndian { |
| 1339 | 1405 | } |
| 1340 | 1406 | |
| 1341 | 1407 | test takeEnum { |
| 1342 | return error.Unimplemented; | |
| 1408 | var r: Reader = .fixed(&.{ 2, 0, 1 }); | |
| 1409 | const E1 = enum(u8) { a, b, c }; | |
| 1410 | const E2 = enum(u16) { _ }; | |
| 1411 | try testing.expectEqual(E1.c, try r.takeEnum(E1, .little)); | |
| 1412 | try testing.expectEqual(@as(E2, @enumFromInt(0x0001)), try r.takeEnum(E2, .big)); | |
| 1343 | 1413 | } |
| 1344 | 1414 | |
| 1345 | 1415 | test takeLeb128 { |
lib/std/io/Writer.zig+34-26| ... | ... | @@ -866,35 +866,31 @@ pub fn printValue( |
| 866 | 866 | } |
| 867 | 867 | const enum_info = @typeInfo(T).@"enum"; |
| 868 | 868 | if (enum_info.is_exhaustive) { |
| 869 | var vecs: [3][]const u8 = .{ @typeName(T), ".", @tagName(value) }; | |
| 869 | var vecs: [2][]const u8 = .{ ".", @tagName(value) }; | |
| 870 | 870 | try w.writeVecAll(&vecs); |
| 871 | 871 | return; |
| 872 | 872 | } |
| 873 | try w.writeAll(@typeName(T)); | |
| 874 | @setEvalBranchQuota(3 * enum_info.fields.len); | |
| 875 | inline for (enum_info.fields) |field| { | |
| 876 | if (@intFromEnum(value) == field.value) { | |
| 877 | try w.writeAll("."); | |
| 878 | try w.writeAll(@tagName(value)); | |
| 879 | return; | |
| 880 | } | |
| 873 | if (std.enums.tagName(T, value)) |tag_name| { | |
| 874 | var vecs: [2][]const u8 = .{ ".", tag_name }; | |
| 875 | try w.writeVecAll(&vecs); | |
| 876 | return; | |
| 881 | 877 | } |
| 882 | try w.writeByte('('); | |
| 878 | try w.writeAll("@enumFromInt("); | |
| 883 | 879 | try w.printValue(ANY, options, @intFromEnum(value), max_depth); |
| 884 | 880 | try w.writeByte(')'); |
| 881 | return; | |
| 885 | 882 | }, |
| 886 | 883 | .@"union" => |info| { |
| 887 | 884 | if (!is_any) { |
| 888 | 885 | if (fmt.len != 0) invalidFmtError(fmt, value); |
| 889 | 886 | return printValue(w, ANY, options, value, max_depth); |
| 890 | 887 | } |
| 891 | try w.writeAll(@typeName(T)); | |
| 892 | 888 | if (max_depth == 0) { |
| 893 | try w.writeAll("{ ... }"); | |
| 889 | try w.writeAll(".{ ... }"); | |
| 894 | 890 | return; |
| 895 | 891 | } |
| 896 | 892 | if (info.tag_type) |UnionTagType| { |
| 897 | try w.writeAll("{ ."); | |
| 893 | try w.writeAll(".{ ."); | |
| 898 | 894 | try w.writeAll(@tagName(@as(UnionTagType, value))); |
| 899 | 895 | try w.writeAll(" = "); |
| 900 | 896 | inline for (info.fields) |u_field| { |
| ... | ... | @@ -903,9 +899,22 @@ pub fn printValue( |
| 903 | 899 | } |
| 904 | 900 | } |
| 905 | 901 | try w.writeAll(" }"); |
| 906 | } else { | |
| 907 | try w.writeByte('@'); | |
| 908 | try w.printIntOptions(@intFromPtr(&value), 16, .lower, options); | |
| 902 | } else switch (info.layout) { | |
| 903 | .auto => { | |
| 904 | return w.writeAll(".{ ... }"); | |
| 905 | }, | |
| 906 | .@"extern", .@"packed" => { | |
| 907 | if (info.fields.len == 0) return w.writeAll(".{}"); | |
| 908 | try w.writeAll(".{ "); | |
| 909 | inline for (info.fields) |field| { | |
| 910 | try w.writeByte('.'); | |
| 911 | try w.writeAll(field.name); | |
| 912 | try w.writeAll(" = "); | |
| 913 | try w.printValue(ANY, options, @field(value, field.name), max_depth - 1); | |
| 914 | (try w.writableArray(2)).* = ", ".*; | |
| 915 | } | |
| 916 | w.buffer[w.end - 2 ..][0..2].* = " }".*; | |
| 917 | }, | |
| 909 | 918 | } |
| 910 | 919 | }, |
| 911 | 920 | .@"struct" => |info| { |
| ... | ... | @@ -916,10 +925,10 @@ pub fn printValue( |
| 916 | 925 | if (info.is_tuple) { |
| 917 | 926 | // Skip the type and field names when formatting tuples. |
| 918 | 927 | if (max_depth == 0) { |
| 919 | try w.writeAll("{ ... }"); | |
| 928 | try w.writeAll(".{ ... }"); | |
| 920 | 929 | return; |
| 921 | 930 | } |
| 922 | try w.writeAll("{"); | |
| 931 | try w.writeAll(".{"); | |
| 923 | 932 | inline for (info.fields, 0..) |f, i| { |
| 924 | 933 | if (i == 0) { |
| 925 | 934 | try w.writeAll(" "); |
| ... | ... | @@ -931,12 +940,11 @@ pub fn printValue( |
| 931 | 940 | try w.writeAll(" }"); |
| 932 | 941 | return; |
| 933 | 942 | } |
| 934 | try w.writeAll(@typeName(T)); | |
| 935 | 943 | if (max_depth == 0) { |
| 936 | try w.writeAll("{ ... }"); | |
| 944 | try w.writeAll(".{ ... }"); | |
| 937 | 945 | return; |
| 938 | 946 | } |
| 939 | try w.writeAll("{"); | |
| 947 | try w.writeAll(".{"); | |
| 940 | 948 | inline for (info.fields, 0..) |f, i| { |
| 941 | 949 | if (i == 0) { |
| 942 | 950 | try w.writeAll(" ."); |
| ... | ... | @@ -1550,7 +1558,7 @@ fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { |
| 1550 | 1558 | } |
| 1551 | 1559 | } |
| 1552 | 1560 | |
| 1553 | test "formatValue max_depth" { | |
| 1561 | test "printValue max_depth" { | |
| 1554 | 1562 | const Vec2 = struct { |
| 1555 | 1563 | const SelfType = @This(); |
| 1556 | 1564 | x: f32, |
| ... | ... | @@ -1595,19 +1603,19 @@ test "formatValue max_depth" { |
| 1595 | 1603 | var buf: [1000]u8 = undefined; |
| 1596 | 1604 | var w: Writer = .fixed(&buf); |
| 1597 | 1605 | try w.printValue("", .{}, inst, 0); |
| 1598 | try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered()); | |
| 1606 | try testing.expectEqualStrings(".{ ... }", w.buffered()); | |
| 1599 | 1607 | |
| 1600 | 1608 | w = .fixed(&buf); |
| 1601 | 1609 | try w.printValue("", .{}, inst, 1); |
| 1602 | try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered()); | |
| 1610 | try testing.expectEqualStrings(".{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }", w.buffered()); | |
| 1603 | 1611 | |
| 1604 | 1612 | w = .fixed(&buf); |
| 1605 | 1613 | try w.printValue("", .{}, inst, 2); |
| 1606 | try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered()); | |
| 1614 | try testing.expectEqualStrings(".{ .a = .{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }, .tu = .{ .ptr = .{ ... } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }", w.buffered()); | |
| 1607 | 1615 | |
| 1608 | 1616 | w = .fixed(&buf); |
| 1609 | 1617 | try w.printValue("", .{}, inst, 3); |
| 1610 | try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ .a = io.Writer.test.printValue max_depth.S{ ... }, .tu = io.Writer.test.printValue max_depth.TU{ ... }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }, .tu = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ .ptr = io.Writer.test.printValue max_depth.TU{ ... } } }, .e = io.Writer.test.printValue max_depth.E.Two, .vec = (10.200,2.220) }", w.buffered()); | |
| 1618 | try testing.expectEqualStrings(".{ .a = .{ .a = .{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }, .tu = .{ .ptr = .{ ... } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }, .tu = .{ .ptr = .{ .ptr = .{ ... } } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }", w.buffered()); | |
| 1611 | 1619 | |
| 1612 | 1620 | const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 }; |
| 1613 | 1621 | w = .fixed(&buf); |
lib/std/net/test.zig+9-33| ... | ... | @@ -5,7 +5,6 @@ const mem = std.mem; |
| 5 | 5 | const testing = std.testing; |
| 6 | 6 | |
| 7 | 7 | test "parse and render IP addresses at comptime" { |
| 8 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 9 | 8 | comptime { |
| 10 | 9 | const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable; |
| 11 | 10 | try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr}); |
| ... | ... | @@ -21,42 +20,23 @@ test "parse and render IP addresses at comptime" { |
| 21 | 20 | } |
| 22 | 21 | |
| 23 | 22 | test "format IPv6 address with no zero runs" { |
| 24 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 25 | 23 | const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0); |
| 26 | 24 | try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr}); |
| 27 | 25 | } |
| 28 | 26 | |
| 29 | 27 | test "parse IPv6 addresses and check compressed form" { |
| 30 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 31 | ||
| 32 | const alloc = testing.allocator; | |
| 33 | ||
| 34 | // 1) Parse an IPv6 address that should compress to [2001:db8::1:0:0:2]:0 | |
| 35 | const addr1 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0); | |
| 36 | ||
| 37 | // 2) Parse an IPv6 address that should compress to [2001:db8::1:2]:0 | |
| 38 | const addr2 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0); | |
| 39 | ||
| 40 | // 3) Parse an IPv6 address that should compress to [2001:db8:1:0:1::2]:0 | |
| 41 | const addr3 = try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0); | |
| 42 | ||
| 43 | // Print each address in Zig's default "[ipv6]:port" form. | |
| 44 | const printed1 = try std.fmt.allocPrint(alloc, "{any}", .{addr1}); | |
| 45 | defer testing.allocator.free(printed1); | |
| 46 | const printed2 = try std.fmt.allocPrint(alloc, "{any}", .{addr2}); | |
| 47 | defer testing.allocator.free(printed2); | |
| 48 | const printed3 = try std.fmt.allocPrint(alloc, "{any}", .{addr3}); | |
| 49 | defer testing.allocator.free(printed3); | |
| 50 | ||
| 51 | // Check the exact compressed forms we expect. | |
| 52 | try std.testing.expectEqualStrings("[2001:db8::1:0:0:2]:0", printed1); | |
| 53 | try std.testing.expectEqualStrings("[2001:db8::1:2]:0", printed2); | |
| 54 | try std.testing.expectEqualStrings("[2001:db8:1:0:1::2]:0", printed3); | |
| 28 | try std.testing.expectFmt("[2001:db8::1:0:0:2]:0", "{f}", .{ | |
| 29 | try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0), | |
| 30 | }); | |
| 31 | try std.testing.expectFmt("[2001:db8::1:2]:0", "{f}", .{ | |
| 32 | try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0), | |
| 33 | }); | |
| 34 | try std.testing.expectFmt("[2001:db8:1:0:1::2]:0", "{f}", .{ | |
| 35 | try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0), | |
| 36 | }); | |
| 55 | 37 | } |
| 56 | 38 | |
| 57 | 39 | test "parse IPv6 address, check raw bytes" { |
| 58 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 59 | ||
| 60 | 40 | const expected_raw: [16]u8 = .{ |
| 61 | 41 | 0x20, 0x01, 0x0d, 0xb8, // 2001:db8 |
| 62 | 42 | 0x00, 0x00, 0x00, 0x00, // :0000:0000 |
| ... | ... | @@ -71,8 +51,6 @@ test "parse IPv6 address, check raw bytes" { |
| 71 | 51 | } |
| 72 | 52 | |
| 73 | 53 | test "parse and render IPv6 addresses" { |
| 74 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 75 | ||
| 76 | 54 | var buffer: [100]u8 = undefined; |
| 77 | 55 | const ips = [_][]const u8{ |
| 78 | 56 | "FF01:0:0:0:0:0:0:FB", |
| ... | ... | @@ -137,8 +115,6 @@ test "invalid but parseable IPv6 scope ids" { |
| 137 | 115 | } |
| 138 | 116 | |
| 139 | 117 | test "parse and render IPv4 addresses" { |
| 140 | if (builtin.os.tag == .wasi) return error.SkipZigTest; | |
| 141 | ||
| 142 | 118 | var buffer: [18]u8 = undefined; |
| 143 | 119 | for ([_][]const u8{ |
| 144 | 120 | "0.0.0.0", |