stable containers: reified approach
- Dominant language
- Zig
- Stars
- 34
- Forks
- 17
- PR merge metrics
- No merged PRs in 30d
Description
The approach that I am considering, which I believe is cleaner than #10, is to generate the structure for the stable container based on an anonymous structure given by the user. That has the advantage that the serialization details are hidden from the user as it's automatically generated. The idea is that the deserialization method and max value are added to a structure generated at compile time.
```zig
const std = @import("std");
const builtin = @import("builtin");
fn StableContainer(comptime T: type, comptime N: usize) !type {
const t_info = @typeInfo(T);
if (t_info != .Struct) {
return error.StableContainerTypeIsNotStruct;
}
const t_struct = t_info.Struct;
// check that all fields are optional
var fields_plus_max: [t_struct.fields.len + 1]std.builtin.Type.StructField = undefined;
inline for (t_struct.fields, 0..) |field, i| {
if (@typeInfo(field.type) != .Optional) {
return error.StableContainerTypeRequiresOptionalFieldTypesOnly;
}
fields_plus_max[i] = field;
}
fields_plus_max[fields_plus_max.len - 1] = std.builtin.Type.StructField{
.name = "sc_max",
.type = usize,
.default_value = &@as(usize, N),
.is_comptime = true,
.alignment = @alignOf(usize),
};
return @Type(.{ .Struct = .{
.layout = t_struct.layout,
.backing_integer = t_struct.backing_integer,
.is_tuple = t_struct.is_tuple,
.decls = t_struct.decls,
.fields = &fields_plus_max,
} });
}
const Payload = struct {
const threshold: u8 = 128;
strength: ?u8,
onoff: ?bool,
};
const StablePayload = StableContainer(Payload, 32) catch |err| @panic(err);
pub fn main() !void {
const payload = StablePayload{ .strength = 1, .onoff = false };
const payload_tinfo = @typeInfo(StablePayload);
const payload_tstruct = payload_tinfo.Struct;
inline for (payload_tstruct.fields) |field| {
std.debug.print("Hello from Zig {any} {s} {any}\n", .{ @field(payload, field.name), field.name, field.is_comptime });
}
inline for (payload_tstruct.decls) |decl| {
std.debug.print("Hello from Zig {any}\n", .{decl});
}
std.debug.print("type name={s} {any}\n", .{@typeName(@TypeOf(payload)), payload_tstruct.decls});
}
```
The issue is that the `@Type` builtin function doesn't work very well with structs, and in fact will not accept declarations (therefore, the `sc_max_size` constant can not be created. For example, merely declaring `Payload.threshold` as `pub` will cause the following error:
```
error: reified structs must have no decls
```
This is a limitation of the language that I have not yet been able to go around and might not be solved before many more iterations of the language.
Contributor guide
No contributing guide indexed for this repository
Research direction
Start with the StableContainer example in the issue and reproduce the `reified structs must have no decls` error using the shown Zig program. Investigate whether the current Zig language supports declarations in structs created with @Type; done would require a viable approach for the generated stable-container metadata described here.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- zig
- Domain
- compilers
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100