I’ve written this one before in 0.15.2. It still works with 0.16, but not on master:
const std = @import("std");
const Duration = std.Io.Duration;
const DurationInterval = struct {
min: Duration,
max: Duration,
};
pub fn main() void {
const d: Duration = .fromSeconds(92);
const di: DurationInterval = .{
.min = .fromSeconds(92),
.max = .fromSeconds(100),
};
std.debug.print("{f}\n", .{d}); // Prints 1m32s, nice!
std.debug.print("{}\n", .{di}); // Prints `.{ .min = .{ .nanoseconds =`, urgh.
std.debug.print("{f}\n", .{dump(di)}); // Prints `.{ .min = 1m32s, .max = 1m40s }`
}
/// Wraps any value in an anonymous formatter that recursively dispatches to `{f}` when a type
/// declares a custom `format` method, or falls back to reflection.
pub fn dump(val: anytype) struct {
data: @TypeOf(val),
fn formatDump(value: anytype, writer: *std.Io.Writer) std.Io.Writer.Error!void {
const ValT = @TypeOf(value);
switch (@typeInfo(ValT)) {
.@"struct", .@"union", .@"enum" => {
if (@hasDecl(ValT, "format")) {
return writer.print("{f}", .{value});
}
},
else => {},
}
switch (@typeInfo(ValT)) {
.@"struct" => |info| {
try writer.writeAll(".{ ");
inline for (info.fields, 0..) |field, i| {
if (i > 0) try writer.writeAll(", ");
if (!info.is_tuple) {
try writer.print(".{s} = ", .{field.name});
}
try formatDump(@field(value, field.name), writer);
}
try writer.writeAll(" }");
},
.optional => {
if (value) |payload| {
try formatDump(payload, writer);
} else {
try writer.writeAll("null");
}
},
.error_union => {
if (value) |payload| {
try formatDump(payload, writer);
} else |err| {
try writer.print("{}", .{err});
}
},
.pointer => |info| switch (info.size) {
.one => try formatDump(value.*, writer),
.slice => {
if (info.child == u8) {
try writer.print("{s}", .{value});
} else {
try writer.writeAll(".{ ");
for (value, 0..) |elem, i| {
if (i > 0) try writer.writeAll(", ");
try formatDump(elem, writer);
}
try writer.writeAll(" }");
}
},
else => try writer.print("{}", .{value}),
},
.array => |info| {
if (info.child == u8) {
try writer.print("{s}", .{value});
} else {
try writer.writeAll(".{ ");
for (value, 0..) |elem, i| {
if (i > 0) try writer.writeAll(", ");
try formatDump(elem, writer);
}
try writer.writeAll(" }");
}
},
else => try writer.print("{}", .{value}),
}
}
pub fn format(self: @This(), writer: *std.Io.Writer) std.Io.Writer.Error!void {
return formatDump(self.data, writer);
}
} {
return .{ .data = val };
}
It doesn’t protect against any recursive types or stuff like that because I didn’t need it. There are likely also other things missing.