Skip to documentation
SLOP

tiny.preserves.records_mod

Reference tiny.preserves records_mod

Defined in tiny.preserves.

Builders for ten kinds of record, each with a fixed label and a fixed number of fields.

API (6)

Actions

Public operations.

Types and contracts

Public types and contracts.

Values and defaults

Public values and defaults.

No direct callersNo direct callstiny.preservesrecords mod
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/preserves/src/records.zig

zig
//! Builders for ten kinds of record, each with a fixed label and a fixed number of fields. A caller//! building one of these records needs the label spelled the one way readers match it, and needs to//! know what the record takes from its arguments.const std = @import("std");const Allocator = std.mem.Allocator;const value_mod = @import("value.zig");const domain_mod = @import("domain.zig");const symbols_mod = @import("symbols.zig");const embedded_mod = @import("embedded.zig");const constructors_mod = @import("constructors.zig");pub const Value = value_mod.Value;pub const NoEmbedded = domain_mod.NoEmbedded;pub const AnyEmbedded = embedded_mod.AnyEmbedded;/// Returns a namespace of protocol record builders for `Value(D)`. Code whose values hold embedded/// values of one type calls it once at compile time, for every protocol record builder over those/// values. `D` has to provide `eql`, `order`, `deinit` and `clone`, or the call is a compile error./// Every builder allocates a copy of the label, one label cell and a copy of the field slice, all/// with `alloc`. The record takes the field values the caller passes, and `deinit` on the record/// frees the label, the fields and the record's own storage. On failure a builder frees its label/// and leaves the fields with the caller.pub fn Records(comptime D: type) type {    domain_mod.assertIsDomain(D);    const V = Value(D);    const H = constructors_mod.Constructors(D);    return struct {        fn recordWithSymbol(alloc: Allocator, symbol_name: []const u8, fields: []const V) !V {            var label = try V.initSymbol(alloc, symbol_name);            errdefer label.deinit(alloc);            return try H.record(alloc, label, fields);        }        /// Returns `<Observe pattern observer>`, for code that asks to observe a pattern. For        /// `AnyEmbedded` values, an observer other than an embedded value is moved into a new cell        /// and wrapped as an embedded value that owns it. The wrapped observer compares, hashes,        /// copies and frees through the value it holds. An observer that is already an embedded        /// value goes in as it is. When the embedded values have a type other than `AnyEmbedded`,        /// every observer goes in as it is. On failure the call frees the wrapper cell and leaves        /// `pattern` and `observer` with the caller.        pub fn observeRecord(alloc: Allocator, pattern: V, observer: V) !V {            var wrapped_ptr: ?*V = null;            const obs: V = observer_wrap: {                if (D == AnyEmbedded) {                    switch (observer) {                        .embedded => break :observer_wrap observer,                        else => {                            const val_ptr = try alloc.create(V);                            val_ptr.* = observer;                            wrapped_ptr = val_ptr;                            break :observer_wrap V{ .embedded = AnyEmbedded{                                .value = @ptrCast(val_ptr),                                .semantic_ops = embedded_mod.parsedEmbeddedOps(V),                                .deinit_fn = embedded_mod.parsedEmbeddedDeinit(V),                                .clone_fn = embedded_mod.parsedEmbeddedClone(V),                            } };                        },                    }                }                break :observer_wrap observer;            };            errdefer if (wrapped_ptr) |ptr| alloc.destroy(ptr);            return recordWithSymbol(alloc, symbols_mod.SYM_OBSERVE.name, &.{ pattern, obs });        }        /// Returns `<Synced>`, a record with zero fields.        pub fn syncedRecord(alloc: Allocator) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_SYNCED.name, &.{});        }        /// Returns `<RequireService name>`.        pub fn requireServiceRecord(alloc: Allocator, name: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_REQUIRE_SERVICE.name, &.{name});        }        /// Returns `<RunService name>`.        pub fn runServiceRecord(alloc: Allocator, name: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_RUN_SERVICE.name, &.{name});        }        /// Returns `<ServiceState name state>`.        pub fn serviceStateRecord(alloc: Allocator, name: V, state: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_SERVICE_STATE.name, &.{ name, state });        }        /// Returns `<ServiceObject name obj>`.        pub fn serviceObjectRecord(alloc: Allocator, name: V, obj: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_SERVICE_OBJECT.name, &.{ name, obj });        }        /// Returns `<ReactorError stage facet reactor err>`, a record with four fields.        pub fn reactorErrorRecord(alloc: Allocator, stage: V, facet: V, reactor: V, err: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_REACTOR_ERROR.name, &.{ stage, facet, reactor, err });        }        /// Returns `<EntityRuntime kind observe during>`.        pub fn entityRuntimeRecord(alloc: Allocator, kind: V, observe: V, during: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_ENTITY_RUNTIME.name, &.{ kind, observe, during });        }        /// Returns `<ServiceDependency depender dependee>`.        pub fn serviceDependencyRecord(alloc: Allocator, depender: V, dependee: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_SERVICE_DEPENDENCY.name, &.{ depender, dependee });        }        /// Returns `<RestartService name>`.        pub fn restartServiceRecord(alloc: Allocator, name: V) !V {            return recordWithSymbol(alloc, symbols_mod.SYM_RESTART_SERVICE.name, &.{name});        }    };}/// The protocol record builders for `Value(NoEmbedded)`. Code whose values are `Value(NoEmbedded)`/// calls these builders, for a namespace fixed to that type.pub const records = Records(NoEmbedded);/// The protocol record builders for values whose embedded values hold any pointer (`AnyEmbedded`)./// The package root re-exports each builder under the same name, so a caller of/// `preserves.observeRecord` calls this instance.pub const any_records = Records(AnyEmbedded);test "syncedRecord builds <Synced>" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var arena = std.heap.ArenaAllocator.init(allocator);    defer arena.deinit();    const a = arena.allocator();    const r = try records.syncedRecord(a);    try std.testing.expect(r == .record);    try std.testing.expect(std.mem.eql(u8, r.record.label.*.symbol, "Synced"));    try std.testing.expectEqual(@as(usize, 0), r.record.fields.len);    _ = V;}test "requireServiceRecord and runServiceRecord take a single name" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var arena = std.heap.ArenaAllocator.init(allocator);    defer arena.deinit();    const a = arena.allocator();    const name = try V.initString(a, "svc-a");    const req = try records.requireServiceRecord(a, name);    try std.testing.expect(std.mem.eql(u8, req.record.label.*.symbol, "RequireService"));    try std.testing.expectEqual(@as(usize, 1), req.record.fields.len);    const run = try records.runServiceRecord(a, name);    try std.testing.expect(std.mem.eql(u8, run.record.label.*.symbol, "RunService"));}test "observeRecord (NoEmbedded) keeps observer unchanged" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var arena = std.heap.ArenaAllocator.init(allocator);    defer arena.deinit();    const a = arena.allocator();    const pattern: V = .{ .discard = {} };    const observer = V.initBoolean(true);    const rec = try records.observeRecord(a, pattern, observer);    try std.testing.expect(std.mem.eql(u8, rec.record.label.*.symbol, "Observe"));    try std.testing.expectEqual(@as(usize, 2), rec.record.fields.len);    try std.testing.expect(rec.record.fields[1] == .boolean);}test "observeRecord (AnyEmbedded) auto-wraps non-embedded observers" {    const V = Value(AnyEmbedded);    const allocator = std.testing.allocator;    var arena = std.heap.ArenaAllocator.init(allocator);    defer arena.deinit();    const a = arena.allocator();    const pattern: V = .{ .discard = {} };    const observer = V.initBoolean(true);    const rec = try any_records.observeRecord(a, pattern, observer);    try std.testing.expect(std.mem.eql(u8, rec.record.label.*.symbol, "Observe"));    try std.testing.expect(rec.record.fields[1] == .embedded);    try std.testing.expect(        rec.record.fields[1].embedded.semantic_ops == embedded_mod.parsedEmbeddedOps(V),    );    var probe: u32 = 7;    const pre_embedded = V{ .embedded = AnyEmbedded{ .value = &probe } };    const rec2 = try any_records.observeRecord(a, pattern, pre_embedded);    try std.testing.expect(rec2.record.fields[1].embedded.semantic_ops == null);}test "protocol record labels are owned by returned values" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var name = try V.initString(allocator, "svc-a");    var name_moved = false;    errdefer if (!name_moved) name.deinit(allocator);    var observed = try records.observeRecord(allocator, .{ .discard = {} }, V.initBoolean(true));    defer observed.deinit(allocator);    var required = try records.requireServiceRecord(allocator, name);    name_moved = true;    defer required.deinit(allocator);}test "observeRecord owns auto-wrapped embedded observer payload" {    const V = Value(AnyEmbedded);    const allocator = std.testing.allocator;    var observed = try any_records.observeRecord(allocator, .{ .discard = {} }, V.initBoolean(true));    defer observed.deinit(allocator);}fn checkObserveRecordAllocationFailures(allocator: Allocator) !void {    const V = Value(AnyEmbedded);    var observer = try V.initString(allocator, "observer");    var observer_owned = true;    defer if (observer_owned) observer.deinit(allocator);    var observed = try any_records.observeRecord(        allocator,        .{ .discard = {} },        observer,    );    observer_owned = false;    defer observed.deinit(allocator);    try std.testing.expect(observed.record.fields[1] == .embedded);    try std.testing.expect(observed.record.fields[1].embedded.deinit_fn != null);    try std.testing.expect(observed.record.fields[1].embedded.clone_fn != null);}test "observeRecord preserves caller ownership on every allocation failure" {    try std.testing.checkAllAllocationFailures(        std.testing.allocator,        checkObserveRecordAllocationFailures,        .{},    );}test "protocol record builders deinit under owning allocator" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var synced = try records.syncedRecord(allocator);    defer synced.deinit(allocator);    var require_service = try records.requireServiceRecord(allocator, V.initI128(1));    defer require_service.deinit(allocator);    var run_service = try records.runServiceRecord(allocator, V.initI128(2));    defer run_service.deinit(allocator);    var service_state = try records.serviceStateRecord(allocator, V.initI128(3), V.initI128(4));    defer service_state.deinit(allocator);    var service_object = try records.serviceObjectRecord(allocator, V.initI128(5), V.initI128(6));    defer service_object.deinit(allocator);    var reactor_error = try records.reactorErrorRecord(        allocator,        V.initI128(7),        V.initI128(8),        V.initI128(9),        V.initI128(10),    );    defer reactor_error.deinit(allocator);    var entity_runtime = try records.entityRuntimeRecord(allocator, V.initI128(11), V.initI128(12), V.initI128(13));    defer entity_runtime.deinit(allocator);    var service_dependency = try records.serviceDependencyRecord(allocator, V.initI128(14), V.initI128(15));    defer service_dependency.deinit(allocator);    var restart_service = try records.restartServiceRecord(allocator, V.initI128(16));    defer restart_service.deinit(allocator);}test "reactorErrorRecord has correct arity" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var arena = std.heap.ArenaAllocator.init(allocator);    defer arena.deinit();    const a = arena.allocator();    const re = try records.reactorErrorRecord(        a,        V.initI128(1),        V.initI128(2),        V.initI128(3),        V.initI128(4),    );    try std.testing.expect(std.mem.eql(u8, re.record.label.*.symbol, "ReactorError"));    try std.testing.expectEqual(@as(usize, 4), re.record.fields.len);}test "entityRuntime, serviceDependency, restartService, serviceState, serviceObject" {    const V = Value(NoEmbedded);    const allocator = std.testing.allocator;    var arena = std.heap.ArenaAllocator.init(allocator);    defer arena.deinit();    const a = arena.allocator();    const er = try records.entityRuntimeRecord(a, V.initI128(1), V.initI128(2), V.initI128(3));    try std.testing.expect(std.mem.eql(u8, er.record.label.*.symbol, "EntityRuntime"));    const sd = try records.serviceDependencyRecord(a, V.initI128(1), V.initI128(2));    try std.testing.expect(std.mem.eql(u8, sd.record.label.*.symbol, "ServiceDependency"));    const rs = try records.restartServiceRecord(a, V.initI128(1));    try std.testing.expect(std.mem.eql(u8, rs.record.label.*.symbol, "RestartService"));    const ss = try records.serviceStateRecord(a, V.initI128(1), V.initI128(2));    try std.testing.expect(std.mem.eql(u8, ss.record.label.*.symbol, "ServiceState"));    const so = try records.serviceObjectRecord(a, V.initI128(1), V.initI128(2));    try std.testing.expect(std.mem.eql(u8, so.record.label.*.symbol, "ServiceObject"));}

Source: lib/preserves/src/root.zig:116

zig
pub const records_mod = @import("records.zig");

Audit

Definitions1
Public names1
Members0
Version26.7.0
Revisiondaab053ee433