Function formatType [src]

Prototype

pub fn formatType( value: anytype, comptime fmt: []const u8, options: FormatOptions, writer: anytype, max_depth: usize, ) @TypeOf(writer).Error!void

Parameters

fmt: []const u8options: FormatOptionsmax_depth: usize

Source

pub fn formatType( value: anytype, comptime fmt: []const u8, options: FormatOptions, writer: anytype, max_depth: usize, ) @TypeOf(writer).Error!void { const T = @TypeOf(value); const actual_fmt = comptime if (std.mem.eql(u8, fmt, ANY)) defaultSpec(T) else if (fmt.len != 0 and (fmt[0] == '?' or fmt[0] == '!')) switch (@typeInfo(T)) { .optional, .error_union => fmt, else => stripOptionalOrErrorUnionSpec(fmt), } else fmt; if (comptime std.mem.eql(u8, actual_fmt, "*")) { return formatAddress(value, options, writer); } if (std.meta.hasMethod(T, "format")) { return try value.format(actual_fmt, options, writer); } switch (@typeInfo(T)) { .comptime_int, .int, .comptime_float, .float => { return formatValue(value, actual_fmt, options, writer); }, .void => { if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf("void", options, writer); }, .bool => { if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf(if (value) "true" else "false", options, writer); }, .optional => { if (actual_fmt.len == 0 or actual_fmt[0] != '?') @compileError("cannot format optional without a specifier (i.e. {?} or {any})"); const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt); if (value) |payload| { return formatType(payload, remaining_fmt, options, writer, max_depth); } else { return formatBuf("null", options, writer); } }, .error_union => { if (actual_fmt.len == 0 or actual_fmt[0] != '!') @compileError("cannot format error union without a specifier (i.e. {!} or {any})"); const remaining_fmt = comptime stripOptionalOrErrorUnionSpec(actual_fmt); if (value) |payload| { return formatType(payload, remaining_fmt, options, writer, max_depth); } else |err| { return formatType(err, "", options, writer, max_depth); } }, .error_set => { if (actual_fmt.len != 0) invalidFmtError(fmt, value); try writer.writeAll("error."); return writer.writeAll(@errorName(value)); }, .@"enum" => |enumInfo| { try writer.writeAll(@typeName(T)); if (enumInfo.is_exhaustive) { if (actual_fmt.len != 0) invalidFmtError(fmt, value); try writer.writeAll("."); try writer.writeAll(@tagName(value)); return; } // Use @tagName only if value is one of known fields @setEvalBranchQuota(3 * enumInfo.fields.len); inline for (enumInfo.fields) |enumField| { if (@intFromEnum(value) == enumField.value) { try writer.writeAll("."); try writer.writeAll(@tagName(value)); return; } } try writer.writeAll("("); try formatType(@intFromEnum(value), actual_fmt, options, writer, max_depth); try writer.writeAll(")"); }, .@"union" => |info| { if (actual_fmt.len != 0) invalidFmtError(fmt, value); try writer.writeAll(@typeName(T)); if (max_depth == 0) { return writer.writeAll("{ ... }"); } if (info.tag_type) |UnionTagType| { try writer.writeAll("{ ."); try writer.writeAll(@tagName(@as(UnionTagType, value))); try writer.writeAll(" = "); inline for (info.fields) |u_field| { if (value == @field(UnionTagType, u_field.name)) { try formatType(@field(value, u_field.name), ANY, options, writer, max_depth - 1); } } try writer.writeAll(" }"); } else { try format(writer, "@{x}", .{@intFromPtr(&value)}); } }, .@"struct" => |info| { if (actual_fmt.len != 0) invalidFmtError(fmt, value); if (info.is_tuple) { // Skip the type and field names when formatting tuples. if (max_depth == 0) { return writer.writeAll("{ ... }"); } try writer.writeAll("{"); inline for (info.fields, 0..) |f, i| { if (i == 0) { try writer.writeAll(" "); } else { try writer.writeAll(", "); } try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1); } return writer.writeAll(" }"); } try writer.writeAll(@typeName(T)); if (max_depth == 0) { return writer.writeAll("{ ... }"); } try writer.writeAll("{"); inline for (info.fields, 0..) |f, i| { if (i == 0) { try writer.writeAll(" ."); } else { try writer.writeAll(", ."); } try writer.writeAll(f.name); try writer.writeAll(" = "); try formatType(@field(value, f.name), ANY, options, writer, max_depth - 1); } try writer.writeAll(" }"); }, .pointer => |ptr_info| switch (ptr_info.size) { .one => switch (@typeInfo(ptr_info.child)) { .array, .@"enum", .@"union", .@"struct" => { return formatType(value.*, actual_fmt, options, writer, max_depth); }, else => return format(writer, "{s}@{x}", .{ @typeName(ptr_info.child), @intFromPtr(value) }), }, .many, .c => { if (actual_fmt.len == 0) @compileError("cannot format pointer without a specifier (i.e. {s} or {*})"); if (ptr_info.sentinel() != null) { return formatType(mem.span(value), actual_fmt, options, writer, max_depth); } if (actual_fmt[0] == 's' and ptr_info.child == u8) { return formatBuf(mem.span(value), options, writer); } invalidFmtError(fmt, value); }, .slice => { if (actual_fmt.len == 0) @compileError("cannot format slice without a specifier (i.e. {s} or {any})"); if (max_depth == 0) { return writer.writeAll("{ ... }"); } if (actual_fmt[0] == 's' and ptr_info.child == u8) { return formatBuf(value, options, writer); } try writer.writeAll("{ "); for (value, 0..) |elem, i| { try formatType(elem, actual_fmt, options, writer, max_depth - 1); if (i != value.len - 1) { try writer.writeAll(", "); } } try writer.writeAll(" }"); }, }, .array => |info| { if (actual_fmt.len == 0) @compileError("cannot format array without a specifier (i.e. {s} or {any})"); if (max_depth == 0) { return writer.writeAll("{ ... }"); } if (actual_fmt[0] == 's' and info.child == u8) { return formatBuf(&value, options, writer); } try writer.writeAll("{ "); for (value, 0..) |elem, i| { try formatType(elem, actual_fmt, options, writer, max_depth - 1); if (i < value.len - 1) { try writer.writeAll(", "); } } try writer.writeAll(" }"); }, .vector => |info| { if (max_depth == 0) { return writer.writeAll("{ ... }"); } try writer.writeAll("{ "); var i: usize = 0; while (i < info.len) : (i += 1) { try formatType(value[i], actual_fmt, options, writer, max_depth - 1); if (i < info.len - 1) { try writer.writeAll(", "); } } try writer.writeAll(" }"); }, .@"fn" => @compileError("unable to format function body type, use '*const " ++ @typeName(T) ++ "' for a function pointer type"), .type => { if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf(@typeName(value), options, writer); }, .enum_literal => { if (actual_fmt.len != 0) invalidFmtError(fmt, value); const buffer = [_]u8{'.'} ++ @tagName(value); return formatBuf(buffer, options, writer); }, .null => { if (actual_fmt.len != 0) invalidFmtError(fmt, value); return formatBuf("null", options, writer); }, else => @compileError("unable to format type '" ++ @typeName(T) ++ "'"), } }