DVUI

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));
        },
    }
}