Generating fields for file as struct

Is there any way to generate fields for a file, which is struct?
Basically file looks like this:

const Config: Type.Struct = @This();

reg: Register = undefined,

reflect_rx_data_received_on_irq_pin: bool = false,
reflect_tx_data_sent_on_irq_pin: bool = false,
reflect_max_retransmit_on_irq_pin: bool = false,
crc: Crc = .@"1byte",
power: Power = .off,
operational_mode: Mode = .tx,

pub fn init() Config {
    return .{};
}

pub fn fromRegister(self: *Config, opt_data: ?[]const u8) !void { // part of Register interface
    if (opt_data == null or opt_data.?.len == 0) {
        return error.NoData;
    }

    const data = opt_data.?;

    self.reflect_rx_data_received_on_irq_pin = (data[0] & (1 << 6)) > 0;
    self.reflect_tx_data_sent_on_irq_pin = (data[0] & (1 << 5)) > 0;
    self.reflect_max_retransmit_on_irq_pin = (data[0] & (1 << 4)) > 0;
    self.crc = try Crc.fromInt((data[0] & (0b11 << 2)) >> 2);
    self.power = try Power.formInt(data[0] & (1 << 1));
    self.mode = try Mode.fromInt(data[0] & 1);
}

pub fn toRegister(...) []const u8 {...} // reverse fn of fromRegister, also part of Register interface

Situation is that. I have 15 files now and want to test them. These files do some binary changes in hardware registers, and I don’t want to write tests like this, where I must my self put binary value for in/out:

var config = Config.init();
var mock = MockRegister.init(
    null, // expected input to the register
    &.{@as(u8, i) << 4}, // expected output from the register
    1, // amount of bytes in register
    0x00, // register index
    &config, // init interface
);
var reg = mock.register();
config.reg = &reg;
try testing.expectEqual(i, try config.getAutoRetransmitted());

I want to write comptime stuff, so I’ll specify which bits are used for each field, which type this field must be. So when I test it with mocks, I’ll just use something like:

test {
    mock_config = ...; // mocked register interface for `config`
    mock_config.item_1 = some_value_1;
    mock_config.item_2 = some_value_2;
    ...
    mock_config.item_n = some_value_n;
   try config.setAutoRetransmitted(value); // calls mock execution, checks for fields to be passed right, or even passed 
}

setAutoRetransmitted() calls mock which testing fields to be as expected.
May be I could use fromRegister and toRegister, but they’re also need to be tested, and after field generation, these functions can also be generated, since I’ll specify all the settings.

May be too many words, but it’ll clear all scope of the problem.
Is there any way to write comptime or regular function, which will generate fields for me like so:
someFn(type, []u8 bits)
And then to generate some data to use it in mocks, and to generate fromRegister/toRegister.

I would prefer as much comptime, as I can, as this program will run on an low performant hardware, so to store and check this data will not affect it’s work.

@import does exactly this.

Not clear. So I want to dynamically generate fields on comptime, from my table. How @import would solve this issue?
Or you mean, the source of @import?

I mean that

const SomeThing = @import("something.zig")

wraps all pubs from something.zig into struct with name SomeThing.

But I probably did not get your problem correctly, sorry if so.

May be my case is too hard to simply ask it on forum :melting_face:
The case is that:

  • I have a file, which is already struct with some stuff (pub/local functions and fields + some internal consts)
  • I want to generate some fields for at least mock, but this fields must be connected to a struct, which represents it’s bitwise representation from register’s byte or bytes if multiple
    So in the end I’ll have some data structure, which I’ll fill while testing, so it would be easier, to test different combinations of register values, and be sure, that I would not write something wrong to registers, as this can put hardware in a brick mode :brick:.

Now I have to generate bitwise representation by hand, using some nasty loops.
But then I would automatically receive all possible byte combinations and iterate tests by them :thinking:

I think, I must not generate fields for ready to go structure, but only mock. Else it would come to some uncomfortable stuff later.
I’ll stick to only generate some data structure to hold data for mock, and then using this data, I’ll recreate fromRegister and toRegister, by iterating through fields.