getty-zig / getty

A (de)serialization framework for Zig
https://getty.so
MIT License
189 stars 13 forks source link

`getty.de.blocks.Pointer` does not respect type-defined attributes #98

Closed ibokuri closed 1 year ago

ibokuri commented 1 year ago

Description

Problem

The deserialize function of the pointer block calls db.deserialize, where db is a block associated with the pointer's child type. If the child type is using type-defined attributes, a compile error will be raised since there is no deserialize function in the child type's DB, only attributes.

Solution

We're missing attribute-handling logic in the pointer block. In getty.deserialize, we have this to handle attributes:

if (comptime traits.has_attributes(T, db)) {
    switch (@typeInfo(T)) {
        .Struct => {
            return try blocks.Struct.deserialize(allocator, T, deserializer, visitor);
        },
        .Union => {
            return try blocks.Union.deserialize(allocator, T, deserializer, visitor);
        },
        else => @compileError("unexpected type cannot be deserialized using attributes"),
    }
}

Something similar needs to be added to the pointer DB.

How to Reproduce the Bug

const std = @import("std");
const json = @import("json");

pub const WorldState = struct {
    pub const @"getty.db" = struct {
        pub const attributes = .{
            .Container = .{ .ignore_unknown_fields = true },
        };
    };

    const Self = @This();

    last_id: c_int = 0,
};

pub fn main() !void {
    const state = try json.fromSlice(null, *WorldState,
        \\{
        \\  "last_id": 123
        \\}
    );

    std.debug.print("{}\n", .{state.*});
}

Additional Context

Thanks to @Namek for coming across this bug and bringing it up in the Discord!