lib/preserves/src/symbols.zig

daab053ee43316e1809a84551d573ddd1e5bf3d2

 1 //! Named constants for the symbols the package builds and matches: protocol record labels, `null`,
 2 //! and the pattern wire form. A builder and a matcher of the same record have to spell its label
 3 //! the same way, so both read it from one constant.
 4 const std = @import("std");
 5 
 6 /// A symbol's name, held as a byte slice. The package root's `isRecord` takes a label as one, and
 7 /// `symbolEql` compares one with a symbol's bytes. The struct is a separate type from a symbol
 8 /// value (`Value.symbol`), and the constants here are of this type.
 9 pub const Symbol = struct {
10     /// The symbol's bytes. Every constant in this file points at a string literal, so the bytes
11     /// live for the whole program.
12     name: []const u8,
13 
14     /// Returns true when `a` and `b` have the same bytes. The file's test is its one caller.
15     pub fn eql(a: Symbol, b: Symbol) bool {
16         return std.mem.eql(u8, a.name, b.name);
17     }
18 
19     /// Returns the byte order of `a`'s name against `b`'s. The file's test is its one caller.
20     pub fn order(a: Symbol, b: Symbol) std.math.Order {
21         return std.mem.order(u8, a.name, b.name);
22     }
23 };
24 
25 /// The label `Observe` of the `<Observe pattern observer>` record. `observeRecord` writes it, and
26 /// `isObserve`, `observePattern` and `observeObserver` match on it.
27 pub const SYM_OBSERVE = Symbol{ .name = "Observe" };
28 /// The label `Synced`, which `syncedRecord` writes.
29 pub const SYM_SYNCED = Symbol{ .name = "Synced" };
30 /// The label `RequireService`, which `requireServiceRecord` writes.
31 pub const SYM_REQUIRE_SERVICE = Symbol{ .name = "RequireService" };
32 /// The label `RunService`, which `runServiceRecord` writes.
33 pub const SYM_RUN_SERVICE = Symbol{ .name = "RunService" };
34 /// The label `ServiceState`, which `serviceStateRecord` writes.
35 pub const SYM_SERVICE_STATE = Symbol{ .name = "ServiceState" };
36 /// The label `ServiceObject`, which `serviceObjectRecord` writes.
37 pub const SYM_SERVICE_OBJECT = Symbol{ .name = "ServiceObject" };
38 /// The label `ReactorError`, which `reactorErrorRecord` writes.
39 pub const SYM_REACTOR_ERROR = Symbol{ .name = "ReactorError" };
40 /// The label `EntityRuntime`, which `entityRuntimeRecord` writes.
41 pub const SYM_ENTITY_RUNTIME = Symbol{ .name = "EntityRuntime" };
42 /// The label `ServiceDependency`, which `serviceDependencyRecord` writes.
43 pub const SYM_SERVICE_DEPENDENCY = Symbol{ .name = "ServiceDependency" };
44 /// The label `RestartService`, which `restartServiceRecord` writes.
45 pub const SYM_RESTART_SERVICE = Symbol{ .name = "RestartService" };
46 /// The symbol `null`, the value the package uses for JSON's null. `null_val` returns it, the JSON
47 /// decoder makes it from JSON null, and `isNull` matches it.
48 pub const SYM_NULL = Symbol{ .name = "null" };
49 /// The symbol `_`, the wire form of the discard pattern, alone or as the record `<_>`.
50 /// `patternToPreserves` writes `<_>`, and `preservePattern` and `preservesToPattern` read both
51 /// forms as the discard pattern.
52 pub const SYM_DISCARD = Symbol{ .name = "_" };
53 /// The label `bind` of the `<bind P>` record, the wire form of a capture. `patternToPreserves`
54 /// writes it for captures and binds, and `preservePattern` and `preservesToPattern` read it as a
55 /// capture.
56 pub const SYM_BIND_PAT = Symbol{ .name = "bind" };
57 /// The label `lit` of the `<lit v>` record, which matches the value `v` itself.
58 /// `patternToPreserves` writes it around atoms and sets, and `preservePattern` and
59 /// `preservesToPattern` unwrap it.
60 pub const SYM_LIT = Symbol{ .name = "lit" };
61 /// The label `group` of the `<group type {…}>` record, the wire form of a record, sequence or
62 /// dictionary pattern. `patternToPreserves` writes it, and `preservePattern` and
63 /// `preservesToPattern` read it.
64 pub const SYM_GROUP = Symbol{ .name = "group" };
65 /// The label `rec` of `<rec L>`, the type of a group that matches records labeled `L`.
66 /// `patternToPreserves` writes it, and `preservePattern` and `preservesToPattern` read it.
67 pub const SYM_REC = Symbol{ .name = "rec" };
68 /// The label `arr` of `<arr>`, the type of a group that matches sequences. `patternToPreserves`
69 /// writes it, and `preservePattern` and `preservesToPattern` read it.
70 pub const SYM_ARR = Symbol{ .name = "arr" };
71 /// The label `dict` of `<dict>`, the type of a group that matches dictionaries.
72 /// `patternToPreserves` writes it, and `preservePattern` and `preservesToPattern` read it.
73 pub const SYM_DICT = Symbol{ .name = "dict" };
74 
75 test "Symbol equality and ordering" {
76     const a = Symbol{ .name = "alpha" };
77     const b = Symbol{ .name = "alpha" };
78     const c = Symbol{ .name = "beta" };
79     try std.testing.expect(a.eql(b));
80     try std.testing.expect(!a.eql(c));
81     try std.testing.expectEqual(std.math.Order.lt, a.order(c));
82     try std.testing.expectEqual(std.math.Order.eq, a.order(b));
83     try std.testing.expectEqual(std.math.Order.gt, c.order(a));
84 }
85 
86 test "well-known symbols match monolith constants" {
87     try std.testing.expect(std.mem.eql(u8, SYM_OBSERVE.name, "Observe"));
88     try std.testing.expect(std.mem.eql(u8, SYM_NULL.name, "null"));
89     try std.testing.expect(std.mem.eql(u8, SYM_DISCARD.name, "_"));
90     try std.testing.expect(std.mem.eql(u8, SYM_REC.name, "rec"));
91 }