displayField
Display a field within a container. displayField can be used when iterating through a list of fields of varying types. it will call the correct display function based on the type of the field.
Parameters
- src:std.builtin.SourceLocation
- std.builtin.SourceLocation
- ContainerT:type
- type
- field_name:[]const u8
- []const u8
- field_value_ptr:anytype
- anytype
- depth:usize
- usize
- field_option:FieldOptions
- FieldOptions
- options:anytype
- anytype
- al:*dvui.Alignment
- *dvui.Alignment
Source
Implementation
pub fn displayField(
src: std.builtin.SourceLocation,
comptime ContainerT: type,
comptime field_name: []const u8,
field_value_ptr: anytype,
comptime depth: usize,
field_option: FieldOptions,
options: anytype,
al: *dvui.Alignment,
) void {
if (field_option.displayMode() == .none) return;
const PtrT = @TypeOf(field_value_ptr);
if (@typeInfo(PtrT) != .pointer) {
@compileError(std.fmt.comptimePrint("field_value_ptr for field {s} must be a pointer to a field. It is a {s}", .{ field_name, @typeName(PtrT) }));
}
// 1. Display using the field's custom display function if set.
// 2. Display using the type's custom display function if set. (For Structs and Unions)
// 3. Display using the default display functions.
if (field_option.hasCustomDisplayFn()) {
const read_only = @typeInfo(@TypeOf(field_value_ptr)).pointer.is_const or field_option.displayMode() != .read_write;
field_option.customDisplayFn(field_name, @ptrCast(@constCast(field_value_ptr)), read_only, al);
return;
}
switch (@typeInfo(@typeInfo(PtrT).pointer.child)) {
.@"struct", .@"union" => {
const struct_options = findMatchingStructOption(@TypeOf(field_value_ptr.*), field_name, options);
if (struct_options) |so| {
if (so.customDisplayFn) |displayFn| {
const read_only = @typeInfo(@TypeOf(field_value_ptr)).pointer.is_const or field_option.displayMode() != .read_write;
displayFn(field_name, @ptrCast(@constCast(field_value_ptr)), read_only, al);
return;
}
}
},
else => {},
}
switch (@typeInfo(@TypeOf(field_value_ptr))) {
.pointer => |top_ptr| {
switch (@typeInfo(top_ptr.child)) {
.int, .float => displayNumber(src, field_name, field_value_ptr, field_option, al),
.bool => displayBool(src, field_name, field_value_ptr, field_option, al),
.@"enum" => displayEnum(src, field_name, field_value_ptr, field_option, al),
.array => |arr| {
// Array of u8 is only displayed as text if it has a text field option.
if (arr.child == u8 and field_option == .text) {
// Arrays can only currently be shown as const strings. (Don't know why std.mem.span won't work here?)
const slice: []const u8 = if (arr.sentinel() != null) field_value_ptr[0..std.mem.findSentinel(u8, arr.sentinel().?, &field_value_ptr.*)] else &field_value_ptr.*;
displayString(src, field_name, &slice, field_option, al);
} else {
displayArray(src, ContainerT, field_name, field_value_ptr, depth, field_option, options);
}
},
.pointer => |ptr| {
if (ptr.size == .slice and ptr.child == u8 and field_option == .text) {
displayString(src, field_name, field_value_ptr, field_option, al);
} else {
displayPointer(src, ContainerT, field_name, field_value_ptr, depth, field_option, options, al);
}
},
.optional => {
displayOptional(src, ContainerT, field_name, field_value_ptr, depth, field_option, options, al, null);
},
.@"union" => displayUnion(src, field_name, field_value_ptr, depth, field_option, options),
.@"struct" => {
if (depth > 0) {
if (displayStruct(src, field_name, field_value_ptr, depth - 1, field_option, options, null)) |box| {
box.deinit();
}
}
},
.type,
.void,
.noreturn,
.comptime_int,
.comptime_float,
.undefined,
.null,
.error_union,
.error_set,
.@"fn",
.@"opaque",
.frame,
.@"anyframe",
.vector,
.enum_literal,
=> {}, // These types are not displayed
}
},
else => {
validateFieldPtrType(field_name, &.{ .int, .float, .bool, .@"enum", .array, .pointer, .optional, .@"union", .@"struct" }, "displayField", @TypeOf(field_value_ptr));
},
}
}