From 1d763c8b29360a5f3b52747231876b54db1c7ba0 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 30 Jun 2025 10:15:22 -0700 Subject: [PATCH] std: formatted printing no longer prints type names 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 reading --- lib/std/fmt.zig | 57 ++++++++-------- lib/std/io/Reader.zig | 148 +++++++++++++++++++++++++++++++----------- lib/std/io/Writer.zig | 60 +++++++++-------- lib/std/net/test.zig | 42 +++--------- 4 files changed, 178 insertions(+), 129 deletions(-) diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig index 9c368fda56..b4e7dff271 100644 --- a/lib/std/fmt.zig +++ b/lib/std/fmt.zig @@ -996,7 +996,7 @@ test "slice" { x: u8, }; const struct_slice: []const S1 = &[_]S1{ S1{ .x = 8 }, S1{ .x = 42 } }; - try expectFmt("slice: { fmt.test.slice.S1{ .x = 8 }, fmt.test.slice.S1{ .x = 42 } }", "slice: {any}", .{struct_slice}); + try expectFmt("slice: { .{ .x = 8 }, .{ .x = 42 } }", "slice: {any}", .{struct_slice}); } { const S2 = struct { @@ -1007,7 +1007,7 @@ test "slice" { } }; const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } }; - try expectFmt("slice: { fmt.test.slice.S2{ .x = 8 }, fmt.test.slice.S2{ .x = 42 } }", "slice: {any}", .{struct_slice}); + try expectFmt("slice: { .{ .x = 8 }, .{ .x = 42 } }", "slice: {any}", .{struct_slice}); } } @@ -1047,8 +1047,8 @@ test "struct" { field: u8, }; const value = Struct{ .field = 42 }; - try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{value}); - try expectFmt("struct: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{&value}); + try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{value}); + try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{&value}); } { const Struct = struct { @@ -1056,7 +1056,7 @@ test "struct" { b: u1, }; const value = Struct{ .a = 0, .b = 1 }; - try expectFmt("struct: fmt.test.struct.Struct{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); + try expectFmt("struct: .{ .a = 0, .b = 1 }\n", "struct: {}\n", .{value}); } const S = struct { @@ -1069,11 +1069,11 @@ test "struct" { .b = error.Unused, }; - try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst}); + try expectFmt(".{ .a = 456, .b = error.Unused }", "{}", .{inst}); // Tuples - try expectFmt("{ }", "{}", .{.{}}); - try expectFmt("{ -1 }", "{}", .{.{-1}}); - try expectFmt("{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }}); + try expectFmt(".{ }", "{}", .{.{}}); + try expectFmt(".{ -1 }", "{}", .{.{-1}}); + try expectFmt(".{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }}); } test "enum" { @@ -1082,15 +1082,15 @@ test "enum" { Two, }; const value = Enum.Two; - try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{value}); - try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{&value}); - try expectFmt("enum: fmt.test.enum.Enum.One\n", "enum: {}\n", .{Enum.One}); - try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); + try expectFmt("enum: .Two\n", "enum: {}\n", .{value}); + try expectFmt("enum: .Two\n", "enum: {}\n", .{&value}); + try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One}); + try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two}); // test very large enum to verify ct branch quota is large enough // TODO: https://github.com/ziglang/zig/issues/15609 if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) { - try expectFmt("enum: os.windows.win32error.Win32Error.INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION}); + try expectFmt("enum: .INVALID_FUNCTION\n", "enum: {}\n", .{std.os.windows.Win32Error.INVALID_FUNCTION}); } const E = enum { @@ -1101,7 +1101,7 @@ test "enum" { const inst = E.Two; - try expectFmt("fmt.test.enum.E.Two", "{}", .{inst}); + try expectFmt(".Two", "{}", .{inst}); } test "non-exhaustive enum" { @@ -1110,9 +1110,9 @@ test "non-exhaustive enum" { Two = 0xbeef, _, }; - try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One}); - try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); - try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))}); + try expectFmt("enum: .One\n", "enum: {}\n", .{Enum.One}); + try expectFmt("enum: .Two\n", "enum: {}\n", .{Enum.Two}); + try expectFmt("enum: @enumFromInt(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))}); try expectFmt("enum: f\n", "enum: {x}\n", .{Enum.One}); try expectFmt("enum: beef\n", "enum: {x}\n", .{Enum.Two}); try expectFmt("enum: BEEF\n", "enum: {X}\n", .{Enum.Two}); @@ -1291,18 +1291,13 @@ test "union" { int: u32, }; - const tu_inst = TU{ .int = 123 }; - const uu_inst = UU{ .int = 456 }; - const eu_inst = EU{ .float = 321.123 }; + const tu_inst: TU = .{ .int = 123 }; + const uu_inst: UU = .{ .int = 456 }; + const eu_inst: EU = .{ .float = 321.123 }; - try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst}); - - var buf: [100]u8 = undefined; - const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); - try std.testing.expectEqualStrings("fmt.test.union.UU@", uu_result[0..18]); - - const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); - try std.testing.expectEqualStrings("fmt.test.union.EU@", eu_result[0..18]); + try expectFmt(".{ .int = 123 }", "{}", .{tu_inst}); + try expectFmt(".{ ... }", "{}", .{uu_inst}); + try expectFmt(".{ .float = 321.123, .int = 1134596030 }", "{}", .{eu_inst}); } test "struct.self-referential" { @@ -1316,7 +1311,7 @@ test "struct.self-referential" { }; inst.a = &inst; - 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}); + try expectFmt(".{ .a = .{ .a = .{ .a = .{ ... } } } }", "{}", .{inst}); } test "struct.zero-size" { @@ -1331,7 +1326,7 @@ test "struct.zero-size" { const a = A{}; const b = B{ .a = a, .c = 0 }; - try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b}); + try expectFmt(".{ .a = .{ }, .c = 0 }", "{}", .{b}); } /// Encodes a sequence of bytes as hexadecimal digits. diff --git a/lib/std/io/Reader.zig b/lib/std/io/Reader.zig index a3e1974049..abb19e6cee 100644 --- a/lib/std/io/Reader.zig +++ b/lib/std/io/Reader.zig @@ -36,7 +36,10 @@ pub const VTable = struct { /// sizes combined with short reads (returning a value less than `limit`) /// in order to minimize complexity. /// - /// This function is always called when `buffer` is empty. + /// Although this function is usually called when `buffer` is empty, it is + /// also called when it needs to be filled more due to the API user + /// requesting contiguous memory. In either case, the existing buffer data + /// should be ignored; new data written to `w`. stream: *const fn (r: *Reader, w: *Writer, limit: Limit) StreamError!usize, /// Consumes bytes from the internally tracked stream position without @@ -194,7 +197,7 @@ pub fn streamRemaining(r: *Reader, w: *Writer) StreamRemainingError!usize { /// Consumes the stream until the end, ignoring all the data, returning the /// number of bytes discarded. pub fn discardRemaining(r: *Reader) ShortError!usize { - var offset: usize = r.end; + var offset: usize = r.end - r.seek; r.seek = 0; r.end = 0; while (true) { @@ -693,6 +696,17 @@ pub fn takeSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel return result; } +/// Returns a slice of the next bytes of buffered data from the stream until +/// `sentinel` is found, without advancing the seek position. +/// +/// Returned slice has a sentinel; end of stream does not count as a delimiter. +/// +/// Invalidates previously returned values from `peek`. +/// +/// See also: +/// * `takeSentinel` +/// * `peekDelimiterExclusive` +/// * `peekDelimiterInclusive` pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 { const result = try r.peekDelimiterInclusive(sentinel); return result[0 .. result.len - 1 :sentinel]; @@ -733,28 +747,38 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { @branchHint(.likely); return buffer[seek .. end + 1]; } - if (seek > 0) { - const remainder = buffer[seek..]; - @memmove(buffer[0..remainder.len], remainder); - r.end = remainder.len; - r.seek = 0; - } - var writer: Writer = .{ - .buffer = r.buffer, - .vtable = &.{ .drain = Writer.fixedDrain }, - }; - while (r.end < r.buffer.len) { - writer.end = r.end; - const n = r.vtable.stream(r, &writer, .limited(r.buffer.len - r.end)) catch |err| switch (err) { + while (r.buffer.len - r.end != 0) { + const end_cap = r.buffer[r.end..]; + var writer: Writer = .fixed(end_cap); + const n = r.vtable.stream(r, &writer, .limited(end_cap.len)) catch |err| switch (err) { error.WriteFailed => unreachable, else => |e| return e, }; - const prev_end = r.end; - r.end = prev_end + n; - if (std.mem.indexOfScalarPos(u8, r.buffer[0..r.end], prev_end, delimiter)) |end| { - return r.buffer[0 .. end + 1]; + r.end += n; + if (std.mem.indexOfScalarPos(u8, end_cap[0..n], 0, delimiter)) |end| { + return r.buffer[seek .. r.end - n + end + 1]; } } + var i: usize = 0; + while (seek - i != 0) { + const begin_cap = r.buffer[i..seek]; + var writer: Writer = .fixed(begin_cap); + const n = r.vtable.stream(r, &writer, .limited(begin_cap.len)) catch |err| switch (err) { + error.WriteFailed => unreachable, + else => |e| return e, + }; + i += n; + if (std.mem.indexOfScalarPos(u8, r.buffer[0..seek], i, delimiter)) |end| { + std.mem.rotate(u8, r.buffer, seek); + r.seek = 0; + r.end += i; + return r.buffer[0 .. seek + end + 1]; + } + } else if (i != 0) { + std.mem.rotate(u8, r.buffer, seek); + r.seek = 0; + r.end += i; + } return error.StreamTooLong; } @@ -778,9 +802,10 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { error.EndOfStream => { - if (r.end == 0) return error.EndOfStream; - r.toss(r.end); - return r.buffer[0..r.end]; + const remaining = r.buffer[r.seek..r.end]; + if (remaining.len == 0) return error.EndOfStream; + r.toss(remaining.len); + return remaining; }, else => |e| return e, }; @@ -808,8 +833,10 @@ pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 { const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) { error.EndOfStream => { - if (r.end == 0) return error.EndOfStream; - return r.buffer[0..r.end]; + const remaining = r.buffer[r.seek..r.end]; + if (remaining.len == 0) return error.EndOfStream; + r.toss(remaining.len); + return remaining; }, else => |e| return e, }; @@ -1219,27 +1246,38 @@ test fixed { } test peek { - return error.Unimplemented; + var r: Reader = .fixed("abc"); + try testing.expectEqualStrings("ab", try r.peek(2)); + try testing.expectEqualStrings("a", try r.peek(1)); } test peekGreedy { - return error.Unimplemented; + var r: Reader = .fixed("abc"); + try testing.expectEqualStrings("abc", try r.peekGreedy(1)); } test toss { - return error.Unimplemented; + var r: Reader = .fixed("abc"); + r.toss(1); + try testing.expectEqualStrings("bc", r.buffered()); } test take { - return error.Unimplemented; + var r: Reader = .fixed("abc"); + try testing.expectEqualStrings("ab", try r.take(2)); + try testing.expectEqualStrings("c", try r.take(1)); } test takeArray { - return error.Unimplemented; + var r: Reader = .fixed("abc"); + try testing.expectEqualStrings("ab", try r.takeArray(2)); + try testing.expectEqualStrings("c", try r.takeArray(1)); } test peekArray { - return error.Unimplemented; + var r: Reader = .fixed("abc"); + try testing.expectEqualStrings("ab", try r.peekArray(2)); + try testing.expectEqualStrings("a", try r.peekArray(1)); } test discardAll { @@ -1251,35 +1289,63 @@ test discardAll { } test discardRemaining { - return error.Unimplemented; + var r: Reader = .fixed("foobar"); + r.toss(1); + try testing.expectEqual(5, try r.discardRemaining()); + try testing.expectEqual(0, try r.discardRemaining()); } test stream { - return error.Unimplemented; + var out_buffer: [10]u8 = undefined; + var r: Reader = .fixed("foobar"); + var w: Writer = .fixed(&out_buffer); + // Short streams are possible with this function but not with fixed. + try testing.expectEqual(2, try r.stream(&w, .limited(2))); + try testing.expectEqualStrings("fo", w.buffered()); + try testing.expectEqual(4, try r.stream(&w, .unlimited)); + try testing.expectEqualStrings("foobar", w.buffered()); } test takeSentinel { - return error.Unimplemented; + var r: Reader = .fixed("ab\nc"); + try testing.expectEqualStrings("ab", try r.takeSentinel('\n')); + try testing.expectError(error.EndOfStream, r.takeSentinel('\n')); + try testing.expectEqualStrings("c", try r.peek(1)); } test peekSentinel { - return error.Unimplemented; + var r: Reader = .fixed("ab\nc"); + try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); + try testing.expectEqualStrings("ab", try r.peekSentinel('\n')); } test takeDelimiterInclusive { - return error.Unimplemented; + var r: Reader = .fixed("ab\nc"); + try testing.expectEqualStrings("ab\n", try r.takeDelimiterInclusive('\n')); + try testing.expectError(error.EndOfStream, r.takeDelimiterInclusive('\n')); } test peekDelimiterInclusive { - return error.Unimplemented; + var r: Reader = .fixed("ab\nc"); + try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); + try testing.expectEqualStrings("ab\n", try r.peekDelimiterInclusive('\n')); + r.toss(3); + try testing.expectError(error.EndOfStream, r.peekDelimiterInclusive('\n')); } test takeDelimiterExclusive { - return error.Unimplemented; + var r: Reader = .fixed("ab\nc"); + try testing.expectEqualStrings("ab", try r.takeDelimiterExclusive('\n')); + try testing.expectEqualStrings("c", try r.takeDelimiterExclusive('\n')); + try testing.expectError(error.EndOfStream, r.takeDelimiterExclusive('\n')); } test peekDelimiterExclusive { - return error.Unimplemented; + var r: Reader = .fixed("ab\nc"); + try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); + try testing.expectEqualStrings("ab", try r.peekDelimiterExclusive('\n')); + r.toss(3); + try testing.expectEqualStrings("c", try r.peekDelimiterExclusive('\n')); } test readDelimiter { @@ -1339,7 +1405,11 @@ test peekStructEndian { } test takeEnum { - return error.Unimplemented; + var r: Reader = .fixed(&.{ 2, 0, 1 }); + const E1 = enum(u8) { a, b, c }; + const E2 = enum(u16) { _ }; + try testing.expectEqual(E1.c, try r.takeEnum(E1, .little)); + try testing.expectEqual(@as(E2, @enumFromInt(0x0001)), try r.takeEnum(E2, .big)); } test takeLeb128 { diff --git a/lib/std/io/Writer.zig b/lib/std/io/Writer.zig index 1602c1559c..b0b2f3529f 100644 --- a/lib/std/io/Writer.zig +++ b/lib/std/io/Writer.zig @@ -866,35 +866,31 @@ pub fn printValue( } const enum_info = @typeInfo(T).@"enum"; if (enum_info.is_exhaustive) { - var vecs: [3][]const u8 = .{ @typeName(T), ".", @tagName(value) }; + var vecs: [2][]const u8 = .{ ".", @tagName(value) }; try w.writeVecAll(&vecs); return; } - try w.writeAll(@typeName(T)); - @setEvalBranchQuota(3 * enum_info.fields.len); - inline for (enum_info.fields) |field| { - if (@intFromEnum(value) == field.value) { - try w.writeAll("."); - try w.writeAll(@tagName(value)); - return; - } + if (std.enums.tagName(T, value)) |tag_name| { + var vecs: [2][]const u8 = .{ ".", tag_name }; + try w.writeVecAll(&vecs); + return; } - try w.writeByte('('); + try w.writeAll("@enumFromInt("); try w.printValue(ANY, options, @intFromEnum(value), max_depth); try w.writeByte(')'); + return; }, .@"union" => |info| { if (!is_any) { if (fmt.len != 0) invalidFmtError(fmt, value); return printValue(w, ANY, options, value, max_depth); } - try w.writeAll(@typeName(T)); if (max_depth == 0) { - try w.writeAll("{ ... }"); + try w.writeAll(".{ ... }"); return; } if (info.tag_type) |UnionTagType| { - try w.writeAll("{ ."); + try w.writeAll(".{ ."); try w.writeAll(@tagName(@as(UnionTagType, value))); try w.writeAll(" = "); inline for (info.fields) |u_field| { @@ -903,9 +899,22 @@ pub fn printValue( } } try w.writeAll(" }"); - } else { - try w.writeByte('@'); - try w.printIntOptions(@intFromPtr(&value), 16, .lower, options); + } else switch (info.layout) { + .auto => { + return w.writeAll(".{ ... }"); + }, + .@"extern", .@"packed" => { + if (info.fields.len == 0) return w.writeAll(".{}"); + try w.writeAll(".{ "); + inline for (info.fields) |field| { + try w.writeByte('.'); + try w.writeAll(field.name); + try w.writeAll(" = "); + try w.printValue(ANY, options, @field(value, field.name), max_depth - 1); + (try w.writableArray(2)).* = ", ".*; + } + w.buffer[w.end - 2 ..][0..2].* = " }".*; + }, } }, .@"struct" => |info| { @@ -916,10 +925,10 @@ pub fn printValue( if (info.is_tuple) { // Skip the type and field names when formatting tuples. if (max_depth == 0) { - try w.writeAll("{ ... }"); + try w.writeAll(".{ ... }"); return; } - try w.writeAll("{"); + try w.writeAll(".{"); inline for (info.fields, 0..) |f, i| { if (i == 0) { try w.writeAll(" "); @@ -931,12 +940,11 @@ pub fn printValue( try w.writeAll(" }"); return; } - try w.writeAll(@typeName(T)); if (max_depth == 0) { - try w.writeAll("{ ... }"); + try w.writeAll(".{ ... }"); return; } - try w.writeAll("{"); + try w.writeAll(".{"); inline for (info.fields, 0..) |f, i| { if (i == 0) { try w.writeAll(" ."); @@ -1550,7 +1558,7 @@ fn writeMultipleOf7Leb128(w: *Writer, value: anytype) Error!void { } } -test "formatValue max_depth" { +test "printValue max_depth" { const Vec2 = struct { const SelfType = @This(); x: f32, @@ -1595,19 +1603,19 @@ test "formatValue max_depth" { var buf: [1000]u8 = undefined; var w: Writer = .fixed(&buf); try w.printValue("", .{}, inst, 0); - try testing.expectEqualStrings("io.Writer.test.printValue max_depth.S{ ... }", w.buffered()); + try testing.expectEqualStrings(".{ ... }", w.buffered()); w = .fixed(&buf); try w.printValue("", .{}, inst, 1); - 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()); + try testing.expectEqualStrings(".{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }", w.buffered()); w = .fixed(&buf); try w.printValue("", .{}, inst, 2); - 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()); + try testing.expectEqualStrings(".{ .a = .{ .a = .{ ... }, .tu = .{ ... }, .e = .Two, .vec = .{ ... } }, .tu = .{ .ptr = .{ ... } }, .e = .Two, .vec = .{ .x = 10.2, .y = 2.22 } }", w.buffered()); w = .fixed(&buf); try w.printValue("", .{}, inst, 3); - 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()); + 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()); const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 }; w = .fixed(&buf); diff --git a/lib/std/net/test.zig b/lib/std/net/test.zig index 413f95ae15..02c927d566 100644 --- a/lib/std/net/test.zig +++ b/lib/std/net/test.zig @@ -5,7 +5,6 @@ const mem = std.mem; const testing = std.testing; test "parse and render IP addresses at comptime" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; comptime { const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable; try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr}); @@ -21,42 +20,23 @@ test "parse and render IP addresses at comptime" { } test "format IPv6 address with no zero runs" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; const addr = try std.net.Address.parseIp6("2001:db8:1:2:3:4:5:6", 0); try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr}); } test "parse IPv6 addresses and check compressed form" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; - - const alloc = testing.allocator; - - // 1) Parse an IPv6 address that should compress to [2001:db8::1:0:0:2]:0 - const addr1 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0); - - // 2) Parse an IPv6 address that should compress to [2001:db8::1:2]:0 - const addr2 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0); - - // 3) Parse an IPv6 address that should compress to [2001:db8:1:0:1::2]:0 - const addr3 = try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0); - - // Print each address in Zig's default "[ipv6]:port" form. - const printed1 = try std.fmt.allocPrint(alloc, "{any}", .{addr1}); - defer testing.allocator.free(printed1); - const printed2 = try std.fmt.allocPrint(alloc, "{any}", .{addr2}); - defer testing.allocator.free(printed2); - const printed3 = try std.fmt.allocPrint(alloc, "{any}", .{addr3}); - defer testing.allocator.free(printed3); - - // Check the exact compressed forms we expect. - try std.testing.expectEqualStrings("[2001:db8::1:0:0:2]:0", printed1); - try std.testing.expectEqualStrings("[2001:db8::1:2]:0", printed2); - try std.testing.expectEqualStrings("[2001:db8:1:0:1::2]:0", printed3); + try std.testing.expectFmt("[2001:db8::1:0:0:2]:0", "{f}", .{ + try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0), + }); + try std.testing.expectFmt("[2001:db8::1:2]:0", "{f}", .{ + try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0), + }); + try std.testing.expectFmt("[2001:db8:1:0:1::2]:0", "{f}", .{ + try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 0), + }); } test "parse IPv6 address, check raw bytes" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; - const expected_raw: [16]u8 = .{ 0x20, 0x01, 0x0d, 0xb8, // 2001:db8 0x00, 0x00, 0x00, 0x00, // :0000:0000 @@ -71,8 +51,6 @@ test "parse IPv6 address, check raw bytes" { } test "parse and render IPv6 addresses" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; - var buffer: [100]u8 = undefined; const ips = [_][]const u8{ "FF01:0:0:0:0:0:0:FB", @@ -137,8 +115,6 @@ test "invalid but parseable IPv6 scope ids" { } test "parse and render IPv4 addresses" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; - var buffer: [18]u8 = undefined; for ([_][]const u8{ "0.0.0.0",