blockblaz / blockblaz/ssz.zig

stable containers: reified approach

Open
#11 0 comments 0 reactions 0 assignees View on GitHub
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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.