#Better way to set a struct field from a runtime string?

1 messages · Page 1 of 1 (latest)

vestal flame
#
const ServerFeatures = packed struct {
    yellowtext: bool,
    flipping: bool,
    customobjections: bool,
    fastloading: bool,
    noencryption: bool,
    deskmod: bool,
    evidence: bool,
    cccc_ic_support: bool,
    arup: bool,
    casing_alerts: bool,
    modcall_reason: bool,
    looping_sfx: bool,
    additive: bool,
    effects: bool,
    y_offset: bool,
    expanded_desk_mods: bool,
    auth_packet: bool,

    fn fromString(s: []const u8) !ServerFeatures {
        const E = comptime b: {
            const fields = @typeInfo(ServerFeatures).Struct.fields;
            var en_fi: [fields.len]std.builtin.Type.EnumField = undefined;
            for(fields, &en_fi, 0..) |field, *d, i| {
                d.* = .{.name = field.name, .value = i};
            }
            break :b @Type(std.builtin.Type{.Enum = .{.tag_type = @typeInfo(ServerFeatures).Struct.backing_integer.?, .fields = &en_fi, .decls = &.{}, .is_exhaustive = false}});
        };
        var sf: ServerFeatures = std.mem.zeroes(ServerFeatures);
        switch(@enumToInt(std.meta.stringToEnum(E, s) orelse return error.Unknown)) {
            inline 0...(@typeInfo(E).Enum.fields.len - 1) => |e| {
                @field(sf, @tagName(@intToEnum(E, e))) = true;
            },
            else => unreachable,
        }
        return sf;
    }
};

This is messy, but I can't think of anything better. Can anyone else?

woven lichen
#
fn fromString(str: []const u8) error{Unknown}!ServerOffset {
    return for (@typeInfo(ServerFeatures).Struct.fields) |field| {
        if (!std.mem.eql(u8, str, field.name)) continue;
        var result = std.mem.zeroes(ServerFeatures);
        @field(result, field.name) = true;
        break result;
    } else error.Unknown;
}
vestal flame
#

oh my god I am so stupid

#

thank you

woven lichen
#

it chill

#

just a bit of over-engineering brain

#

we all been there

vestal flame
#

bash programmer mindset :P

woven lichen
#

fr fr

vestal flame
# woven lichen fr fr

also, do you know why inline else => |capture| doesn't work for enums? just curious

woven lichen
#

it should work afaik

vestal flame
#

👀

woven lichen
#

even else => |capture| ought to work for enums now

#

make sure you're using latest master and everything

vestal flame
#

yeah

vestal flame
woven lichen
#

right, add inline

vestal flame
#

still doesn't work because runtime control flow in comptime block

#

er

woven lichen
#

ah, forgot we still haven't fixed that

vestal flame
#

other way

woven lichen
#
fn fromString(str: []const u8) error{Unknown}!ServerOffset {
    inline for (@typeInfo(ServerFeatures).Struct.fields) |field| {
        if (std.mem.eql(u8, str, field.name)) {
            var result = std.mem.zeroes(ServerFeatures);
            @field(result, field.name) = true;
            return result;
        }
    }
    return error.Unknown;
}
#

just slightly less terse

vestal flame
#

oh, I guess this works

#

so my other comptime abuses could have been fixed similarly easily

#

smh my head

#

and thank you

woven lichen
#

tbf I wouldn't say breaking out of an inline for loop at runtime is an abuse

#

I would say it should work as you'd expect

vestal flame
#

well, no, but the previous one was

woven lichen
#

ah, ye