mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +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,
|
x: u8,
|
||||||
};
|
};
|
||||||
const struct_slice: []const S1 = &[_]S1{ S1{ .x = 8 }, S1{ .x = 42 } };
|
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 {
|
const S2 = struct {
|
||||||
|
|
@ -1007,7 +1007,7 @@ test "slice" {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const struct_slice: []const S2 = &[_]S2{ S2{ .x = 8 }, S2{ .x = 42 } };
|
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,
|
field: u8,
|
||||||
};
|
};
|
||||||
const value = Struct{ .field = 42 };
|
const value = Struct{ .field = 42 };
|
||||||
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: fmt.test.struct.Struct{ .field = 42 }\n", "struct: {}\n", .{&value});
|
try expectFmt("struct: .{ .field = 42 }\n", "struct: {}\n", .{&value});
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
const Struct = struct {
|
const Struct = struct {
|
||||||
|
|
@ -1056,7 +1056,7 @@ test "struct" {
|
||||||
b: u1,
|
b: u1,
|
||||||
};
|
};
|
||||||
const value = Struct{ .a = 0, .b = 1 };
|
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 {
|
const S = struct {
|
||||||
|
|
@ -1069,11 +1069,11 @@ test "struct" {
|
||||||
.b = error.Unused,
|
.b = error.Unused,
|
||||||
};
|
};
|
||||||
|
|
||||||
try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst});
|
try expectFmt(".{ .a = 456, .b = error.Unused }", "{}", .{inst});
|
||||||
// Tuples
|
// Tuples
|
||||||
try expectFmt("{ }", "{}", .{.{}});
|
try expectFmt(".{ }", "{}", .{.{}});
|
||||||
try expectFmt("{ -1 }", "{}", .{.{-1}});
|
try expectFmt(".{ -1 }", "{}", .{.{-1}});
|
||||||
try expectFmt("{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }});
|
try expectFmt(".{ -1, 42, 25000 }", "{}", .{.{ -1, 42, 0.25e5 }});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "enum" {
|
test "enum" {
|
||||||
|
|
@ -1082,15 +1082,15 @@ test "enum" {
|
||||||
Two,
|
Two,
|
||||||
};
|
};
|
||||||
const value = Enum.Two;
|
const value = Enum.Two;
|
||||||
try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{value});
|
try expectFmt("enum: .Two\n", "enum: {}\n", .{value});
|
||||||
try expectFmt("enum: fmt.test.enum.Enum.Two\n", "enum: {}\n", .{&value});
|
try expectFmt("enum: .Two\n", "enum: {}\n", .{&value});
|
||||||
try expectFmt("enum: fmt.test.enum.Enum.One\n", "enum: {}\n", .{Enum.One});
|
try expectFmt("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", .{Enum.Two});
|
||||||
|
|
||||||
// test very large enum to verify ct branch quota is large enough
|
// test very large enum to verify ct branch quota is large enough
|
||||||
// TODO: https://github.com/ziglang/zig/issues/15609
|
// TODO: https://github.com/ziglang/zig/issues/15609
|
||||||
if (!((builtin.cpu.arch == .wasm32) and builtin.mode == .Debug)) {
|
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 {
|
const E = enum {
|
||||||
|
|
@ -1101,7 +1101,7 @@ test "enum" {
|
||||||
|
|
||||||
const inst = E.Two;
|
const inst = E.Two;
|
||||||
|
|
||||||
try expectFmt("fmt.test.enum.E.Two", "{}", .{inst});
|
try expectFmt(".Two", "{}", .{inst});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "non-exhaustive enum" {
|
test "non-exhaustive enum" {
|
||||||
|
|
@ -1110,9 +1110,9 @@ test "non-exhaustive enum" {
|
||||||
Two = 0xbeef,
|
Two = 0xbeef,
|
||||||
_,
|
_,
|
||||||
};
|
};
|
||||||
try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One});
|
try expectFmt("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: .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: @enumFromInt(4660)\n", "enum: {}\n", .{@as(Enum, @enumFromInt(0x1234))});
|
||||||
try expectFmt("enum: f\n", "enum: {x}\n", .{Enum.One});
|
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});
|
||||||
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,
|
int: u32,
|
||||||
};
|
};
|
||||||
|
|
||||||
const tu_inst = TU{ .int = 123 };
|
const tu_inst: TU = .{ .int = 123 };
|
||||||
const uu_inst = UU{ .int = 456 };
|
const uu_inst: UU = .{ .int = 456 };
|
||||||
const eu_inst = EU{ .float = 321.123 };
|
const eu_inst: EU = .{ .float = 321.123 };
|
||||||
|
|
||||||
try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst});
|
try expectFmt(".{ .int = 123 }", "{}", .{tu_inst});
|
||||||
|
try expectFmt(".{ ... }", "{}", .{uu_inst});
|
||||||
var buf: [100]u8 = undefined;
|
try expectFmt(".{ .float = 321.123, .int = 1134596030 }", "{}", .{eu_inst});
|
||||||
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]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "struct.self-referential" {
|
test "struct.self-referential" {
|
||||||
|
|
@ -1316,7 +1311,7 @@ test "struct.self-referential" {
|
||||||
};
|
};
|
||||||
inst.a = &inst;
|
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" {
|
test "struct.zero-size" {
|
||||||
|
|
@ -1331,7 +1326,7 @@ test "struct.zero-size" {
|
||||||
const a = A{};
|
const a = A{};
|
||||||
const b = B{ .a = a, .c = 0 };
|
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.
|
/// 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`)
|
/// sizes combined with short reads (returning a value less than `limit`)
|
||||||
/// in order to minimize complexity.
|
/// 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,
|
stream: *const fn (r: *Reader, w: *Writer, limit: Limit) StreamError!usize,
|
||||||
|
|
||||||
/// Consumes bytes from the internally tracked stream position without
|
/// 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
|
/// Consumes the stream until the end, ignoring all the data, returning the
|
||||||
/// number of bytes discarded.
|
/// number of bytes discarded.
|
||||||
pub fn discardRemaining(r: *Reader) ShortError!usize {
|
pub fn discardRemaining(r: *Reader) ShortError!usize {
|
||||||
var offset: usize = r.end;
|
var offset: usize = r.end - r.seek;
|
||||||
r.seek = 0;
|
r.seek = 0;
|
||||||
r.end = 0;
|
r.end = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
|
@ -693,6 +696,17 @@ pub fn takeSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel
|
||||||
return result;
|
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 {
|
pub fn peekSentinel(r: *Reader, comptime sentinel: u8) DelimiterError![:sentinel]u8 {
|
||||||
const result = try r.peekDelimiterInclusive(sentinel);
|
const result = try r.peekDelimiterInclusive(sentinel);
|
||||||
return result[0 .. result.len - 1 :sentinel];
|
return result[0 .. result.len - 1 :sentinel];
|
||||||
|
|
@ -733,28 +747,38 @@ pub fn peekDelimiterInclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
|
||||||
@branchHint(.likely);
|
@branchHint(.likely);
|
||||||
return buffer[seek .. end + 1];
|
return buffer[seek .. end + 1];
|
||||||
}
|
}
|
||||||
if (seek > 0) {
|
while (r.buffer.len - r.end != 0) {
|
||||||
const remainder = buffer[seek..];
|
const end_cap = r.buffer[r.end..];
|
||||||
@memmove(buffer[0..remainder.len], remainder);
|
var writer: Writer = .fixed(end_cap);
|
||||||
r.end = remainder.len;
|
const n = r.vtable.stream(r, &writer, .limited(end_cap.len)) catch |err| switch (err) {
|
||||||
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) {
|
|
||||||
error.WriteFailed => unreachable,
|
error.WriteFailed => unreachable,
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
const prev_end = r.end;
|
r.end += n;
|
||||||
r.end = prev_end + n;
|
if (std.mem.indexOfScalarPos(u8, end_cap[0..n], 0, delimiter)) |end| {
|
||||||
if (std.mem.indexOfScalarPos(u8, r.buffer[0..r.end], prev_end, delimiter)) |end| {
|
return r.buffer[seek .. r.end - n + end + 1];
|
||||||
return r.buffer[0 .. 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;
|
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 {
|
pub fn takeDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
|
||||||
const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
|
const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
|
||||||
error.EndOfStream => {
|
error.EndOfStream => {
|
||||||
if (r.end == 0) return error.EndOfStream;
|
const remaining = r.buffer[r.seek..r.end];
|
||||||
r.toss(r.end);
|
if (remaining.len == 0) return error.EndOfStream;
|
||||||
return r.buffer[0..r.end];
|
r.toss(remaining.len);
|
||||||
|
return remaining;
|
||||||
},
|
},
|
||||||
else => |e| return e,
|
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 {
|
pub fn peekDelimiterExclusive(r: *Reader, delimiter: u8) DelimiterError![]u8 {
|
||||||
const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
|
const result = r.peekDelimiterInclusive(delimiter) catch |err| switch (err) {
|
||||||
error.EndOfStream => {
|
error.EndOfStream => {
|
||||||
if (r.end == 0) return error.EndOfStream;
|
const remaining = r.buffer[r.seek..r.end];
|
||||||
return r.buffer[0..r.end];
|
if (remaining.len == 0) return error.EndOfStream;
|
||||||
|
r.toss(remaining.len);
|
||||||
|
return remaining;
|
||||||
},
|
},
|
||||||
else => |e| return e,
|
else => |e| return e,
|
||||||
};
|
};
|
||||||
|
|
@ -1219,27 +1246,38 @@ test fixed {
|
||||||
}
|
}
|
||||||
|
|
||||||
test peek {
|
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 {
|
test peekGreedy {
|
||||||
return error.Unimplemented;
|
var r: Reader = .fixed("abc");
|
||||||
|
try testing.expectEqualStrings("abc", try r.peekGreedy(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
test toss {
|
test toss {
|
||||||
return error.Unimplemented;
|
var r: Reader = .fixed("abc");
|
||||||
|
r.toss(1);
|
||||||
|
try testing.expectEqualStrings("bc", r.buffered());
|
||||||
}
|
}
|
||||||
|
|
||||||
test take {
|
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 {
|
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 {
|
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 {
|
test discardAll {
|
||||||
|
|
@ -1251,35 +1289,63 @@ test discardAll {
|
||||||
}
|
}
|
||||||
|
|
||||||
test discardRemaining {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
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 {
|
test readDelimiter {
|
||||||
|
|
@ -1339,7 +1405,11 @@ test peekStructEndian {
|
||||||
}
|
}
|
||||||
|
|
||||||
test takeEnum {
|
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 {
|
test takeLeb128 {
|
||||||
|
|
|
||||||
|
|
@ -866,35 +866,31 @@ pub fn printValue(
|
||||||
}
|
}
|
||||||
const enum_info = @typeInfo(T).@"enum";
|
const enum_info = @typeInfo(T).@"enum";
|
||||||
if (enum_info.is_exhaustive) {
|
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);
|
try w.writeVecAll(&vecs);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try w.writeAll(@typeName(T));
|
if (std.enums.tagName(T, value)) |tag_name| {
|
||||||
@setEvalBranchQuota(3 * enum_info.fields.len);
|
var vecs: [2][]const u8 = .{ ".", tag_name };
|
||||||
inline for (enum_info.fields) |field| {
|
try w.writeVecAll(&vecs);
|
||||||
if (@intFromEnum(value) == field.value) {
|
return;
|
||||||
try w.writeAll(".");
|
|
||||||
try w.writeAll(@tagName(value));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
try w.writeByte('(');
|
try w.writeAll("@enumFromInt(");
|
||||||
try w.printValue(ANY, options, @intFromEnum(value), max_depth);
|
try w.printValue(ANY, options, @intFromEnum(value), max_depth);
|
||||||
try w.writeByte(')');
|
try w.writeByte(')');
|
||||||
|
return;
|
||||||
},
|
},
|
||||||
.@"union" => |info| {
|
.@"union" => |info| {
|
||||||
if (!is_any) {
|
if (!is_any) {
|
||||||
if (fmt.len != 0) invalidFmtError(fmt, value);
|
if (fmt.len != 0) invalidFmtError(fmt, value);
|
||||||
return printValue(w, ANY, options, value, max_depth);
|
return printValue(w, ANY, options, value, max_depth);
|
||||||
}
|
}
|
||||||
try w.writeAll(@typeName(T));
|
|
||||||
if (max_depth == 0) {
|
if (max_depth == 0) {
|
||||||
try w.writeAll("{ ... }");
|
try w.writeAll(".{ ... }");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (info.tag_type) |UnionTagType| {
|
if (info.tag_type) |UnionTagType| {
|
||||||
try w.writeAll("{ .");
|
try w.writeAll(".{ .");
|
||||||
try w.writeAll(@tagName(@as(UnionTagType, value)));
|
try w.writeAll(@tagName(@as(UnionTagType, value)));
|
||||||
try w.writeAll(" = ");
|
try w.writeAll(" = ");
|
||||||
inline for (info.fields) |u_field| {
|
inline for (info.fields) |u_field| {
|
||||||
|
|
@ -903,9 +899,22 @@ pub fn printValue(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
try w.writeAll(" }");
|
try w.writeAll(" }");
|
||||||
} else {
|
} else switch (info.layout) {
|
||||||
try w.writeByte('@');
|
.auto => {
|
||||||
try w.printIntOptions(@intFromPtr(&value), 16, .lower, options);
|
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| {
|
.@"struct" => |info| {
|
||||||
|
|
@ -916,10 +925,10 @@ pub fn printValue(
|
||||||
if (info.is_tuple) {
|
if (info.is_tuple) {
|
||||||
// Skip the type and field names when formatting tuples.
|
// Skip the type and field names when formatting tuples.
|
||||||
if (max_depth == 0) {
|
if (max_depth == 0) {
|
||||||
try w.writeAll("{ ... }");
|
try w.writeAll(".{ ... }");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try w.writeAll("{");
|
try w.writeAll(".{");
|
||||||
inline for (info.fields, 0..) |f, i| {
|
inline for (info.fields, 0..) |f, i| {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
try w.writeAll(" ");
|
try w.writeAll(" ");
|
||||||
|
|
@ -931,12 +940,11 @@ pub fn printValue(
|
||||||
try w.writeAll(" }");
|
try w.writeAll(" }");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try w.writeAll(@typeName(T));
|
|
||||||
if (max_depth == 0) {
|
if (max_depth == 0) {
|
||||||
try w.writeAll("{ ... }");
|
try w.writeAll(".{ ... }");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try w.writeAll("{");
|
try w.writeAll(".{");
|
||||||
inline for (info.fields, 0..) |f, i| {
|
inline for (info.fields, 0..) |f, i| {
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
try w.writeAll(" .");
|
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 Vec2 = struct {
|
||||||
const SelfType = @This();
|
const SelfType = @This();
|
||||||
x: f32,
|
x: f32,
|
||||||
|
|
@ -1595,19 +1603,19 @@ test "formatValue max_depth" {
|
||||||
var buf: [1000]u8 = undefined;
|
var buf: [1000]u8 = undefined;
|
||||||
var w: Writer = .fixed(&buf);
|
var w: Writer = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 0);
|
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);
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 1);
|
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);
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 2);
|
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);
|
w = .fixed(&buf);
|
||||||
try w.printValue("", .{}, inst, 3);
|
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 };
|
const vec: @Vector(4, i32) = .{ 1, 2, 3, 4 };
|
||||||
w = .fixed(&buf);
|
w = .fixed(&buf);
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@ const mem = std.mem;
|
||||||
const testing = std.testing;
|
const testing = std.testing;
|
||||||
|
|
||||||
test "parse and render IP addresses at comptime" {
|
test "parse and render IP addresses at comptime" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
|
||||||
comptime {
|
comptime {
|
||||||
const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
|
const ipv6addr = net.Address.parseIp("::1", 0) catch unreachable;
|
||||||
try std.testing.expectFmt("[::1]:0", "{f}", .{ipv6addr});
|
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" {
|
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);
|
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});
|
try std.testing.expectFmt("[2001:db8:1:2:3:4:5:6]:0", "{f}", .{addr});
|
||||||
}
|
}
|
||||||
|
|
||||||
test "parse IPv6 addresses and check compressed form" {
|
test "parse IPv6 addresses and check compressed form" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
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),
|
||||||
const alloc = testing.allocator;
|
});
|
||||||
|
try std.testing.expectFmt("[2001:db8::1:2]:0", "{f}", .{
|
||||||
// 1) Parse an IPv6 address that should compress to [2001:db8::1:0:0:2]:0
|
try std.net.Address.parseIp6("2001:0db8:0000:0000:0000:0000:0001:0002", 0),
|
||||||
const addr1 = try std.net.Address.parseIp6("2001:0db8:0000:0000:0001:0000:0000:0002", 0);
|
});
|
||||||
|
try std.testing.expectFmt("[2001:db8:1:0:1::2]:0", "{f}", .{
|
||||||
// 2) Parse an IPv6 address that should compress to [2001:db8::1:2]:0
|
try std.net.Address.parseIp6("2001:0db8:0001:0000:0001:0000:0000:0002", 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test "parse IPv6 address, check raw bytes" {
|
test "parse IPv6 address, check raw bytes" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
|
||||||
|
|
||||||
const expected_raw: [16]u8 = .{
|
const expected_raw: [16]u8 = .{
|
||||||
0x20, 0x01, 0x0d, 0xb8, // 2001:db8
|
0x20, 0x01, 0x0d, 0xb8, // 2001:db8
|
||||||
0x00, 0x00, 0x00, 0x00, // :0000:0000
|
0x00, 0x00, 0x00, 0x00, // :0000:0000
|
||||||
|
|
@ -71,8 +51,6 @@ test "parse IPv6 address, check raw bytes" {
|
||||||
}
|
}
|
||||||
|
|
||||||
test "parse and render IPv6 addresses" {
|
test "parse and render IPv6 addresses" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
|
||||||
|
|
||||||
var buffer: [100]u8 = undefined;
|
var buffer: [100]u8 = undefined;
|
||||||
const ips = [_][]const u8{
|
const ips = [_][]const u8{
|
||||||
"FF01:0:0:0:0:0:0:FB",
|
"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" {
|
test "parse and render IPv4 addresses" {
|
||||||
if (builtin.os.tag == .wasi) return error.SkipZigTest;
|
|
||||||
|
|
||||||
var buffer: [18]u8 = undefined;
|
var buffer: [18]u8 = undefined;
|
||||||
for ([_][]const u8{
|
for ([_][]const u8{
|
||||||
"0.0.0.0",
|
"0.0.0.0",
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue