Skip to content

Builder pattern

Description

Builder pattern.

  • Builder wraps an allocator, no other state.
  • createEvent / createSensor build a typed item into a Slot.
  • identifyNodeAs recovers the typed pointer for field access.
  • destroyByTag frees whichever type the Slot holds.

Diagram

 alloc.create ──► slot (non-null)
 Builder.identifyNodeAs ──► field access (no transfer)
 Builder.destroyByTag ──► slot = null (freed)

Source

pub fn builder_pattern(allocator: std.mem.Allocator, io: std.Io) !void {
    _ = io;
    const b: Builder = .{ .alloc = allocator };

    {
        var slot: Slot = null;
        defer b.destroyByTag(&slot);
        try b.createEvent(100, &slot);
        const ev = items.Event.EventPolyHelper.mustIdentifySlotAs(&slot);
        try helpers.expect(error.BuilderFailed, ev.code == 100, "wrong event code");
    }

    {
        var slot: Slot = null;
        defer b.destroyByTag(&slot);
        try b.createSensor(9.8, &slot);
        const sn = items.Sensor.SensorPolyHelper.mustIdentifySlotAs(&slot);
        try helpers.expect(error.BuilderFailed, sn.value == 9.8, "wrong sensor value");
    }
}

pub const Builder = struct {
    alloc: std.mem.Allocator,

    pub fn createEvent(self: Builder, code: i32, slot: *Slot) !void {
        try items.Event.EventPolyHelper.create(self.alloc, slot);
        items.Event.EventPolyHelper.mustIdentifySlotAs(slot).code = code;
    }

    pub fn createSensor(self: Builder, value: f64, slot: *Slot) !void {
        try items.Sensor.SensorPolyHelper.create(self.alloc, slot);
        items.Sensor.SensorPolyHelper.mustIdentifySlotAs(slot).value = value;
    }

    pub fn destroyByTag(self: Builder, slot: *Slot) void {
        items.freeSlot(slot, self.alloc);
    }
};

const items = @import("../items/items.zig");
const helpers = @import("../helpers/helpers.zig");
const polynode = @import("matryoshka").polynode;
const std = @import("std");
const Slot = polynode.Slot;