mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 05:44:20 +00:00
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
This commit is contained in:
parent
7eae26d608
commit
1d763c8b29
4 changed files with 178 additions and 129 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue