#Array of struct with comptime field

1 messages · Page 1 of 1 (latest)

primal sail
#

I have this struct, with a nice api to receive the data associated with the command.
But the issue I have now is that instances of RenderCommand should be stored together in an array.
I am prevented since they are treated as different types, in this case it's frustrating since they are they exactly same size, containing the exact same types.
Does anyone have a suggestion how to solve my issue?

const RenderCommandTag = enum {
    image,
    text,
};

fn RenderCommand(comptime tag: RenderCommandTag) type {
    return struct {
        //
        comptime tag: RenderCommandTag = tag,
        bounding_box: BoundingBox,
        tag_data_idx: u16,
        z_index: u16,

        const Data = switch (tag) {
            .image => DataImage,
            .text => DataText,
        };

        fn getData(self: *const RenderCommand, layout: *const LayoutEngine) *const Data {
            return switch (self.tag) {
                .image => layout.getDataImage(self.tag_data_idx),
                .text => layout.getDataText(self.tag_data_idx),
            };
        }
    };
}
narrow grove
#

and so getData either will return a tagged union or you can make it take a comptime tag argument

#

but he no just make it return a tagged union

primal sail
#

Thanks, I ended up doing this, utilizing the discriminant of the union instead of storing a tag directly.
The only part is that it creates repetition, but well oh well.

const RenderCommand = union(RenderCommandTag) {
    image: struct {
        bounding_box: BoundingBox,
        tag_data_idx: u16 = 0,
        z_index: u16,
        fn getData(self: *const @This(), layout: *const Self) *const DataImage {
            return layout.getDataImage(self.tag_data_idx).?;
        }
    },
    text: struct {
        bounding_box: BoundingBox,
        tag_data_idx: u16 = 0,
        z_index: u16,
        fn getData(self: *const @This(), layout: *const Self) *const DataText {
            return layout.getDataText(self.tag_data_idx).?;
        }
    },
};

// in renderer
for (commands) |cmd| {
    switch (cmd) {
        .image => |info| {
            const data = info.getData(&layout);
            _ = data;
        },
        .text => |info| {
            const data = info.getData(&layout);
            _ = data;
        },
    }
}