@voxgig/sdkgen 4.8.3 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/bin/voxgig-sdkgen +1 -1
  2. package/package.json +1 -1
  3. package/project/.sdk/model/target/zig.aon +9 -0
  4. package/project/.sdk/src/cmp/zig/Package_zig.ts +15 -11
  5. package/project/.sdk/src/cmp/zig/fragment/Entity.fragment.zig +3 -3
  6. package/project/.sdk/src/cmp/zig/fragment/EntityListOp.fragment.zig +3 -3
  7. package/project/.sdk/src/cmp/zig/fragment/Main.fragment.zig +3 -3
  8. package/project/.sdk/src/cmp/zig/utility_zig.ts +50 -1
  9. package/project/.sdk/tm/c/tests/vendor/omni/json.c +2 -2
  10. package/project/.sdk/tm/c/tests/vendor/omni/omni.h +2 -2
  11. package/project/.sdk/tm/c/tests/vendor/omni/runner.c +2 -2
  12. package/project/.sdk/tm/c/tests/vendor/omni/util.c +2 -2
  13. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/json.clj +2 -2
  14. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/runner.clj +2 -2
  15. package/project/.sdk/tm/clojure/test/vendor/omni/voxgig/omni/util.clj +2 -2
  16. package/project/.sdk/tm/cpp/test/vendor/omni/json.hpp +2 -2
  17. package/project/.sdk/tm/cpp/test/vendor/omni/omni.hpp +2 -2
  18. package/project/.sdk/tm/cpp/test/vendor/omni/util.hpp +2 -2
  19. package/project/.sdk/tm/csharp/test/vendor/omni/Runner.cs +2 -2
  20. package/project/.sdk/tm/csharp/test/vendor/omni/Util.cs +2 -2
  21. package/project/.sdk/tm/csharp/utility/struct/Struct.cs +1 -1
  22. package/project/.sdk/tm/dart/test/vendor/omni/omni.dart +2 -2
  23. package/project/.sdk/tm/dart/test/vendor/omni/runner.dart +2 -2
  24. package/project/.sdk/tm/dart/test/vendor/omni/util.dart +2 -2
  25. package/project/.sdk/tm/elixir/test/vendor/omni/json.ex +2 -2
  26. package/project/.sdk/tm/elixir/test/vendor/omni/runner.ex +2 -2
  27. package/project/.sdk/tm/elixir/test/vendor/omni/util.ex +2 -2
  28. package/project/.sdk/tm/go/feature/secrets/plugin/capability.go +1 -1
  29. package/project/.sdk/tm/go/feature/secrets/plugin/catalog.go +1 -1
  30. package/project/.sdk/tm/go/feature/secrets/plugin/config.go +1 -1
  31. package/project/.sdk/tm/go/feature/secrets/plugin/depend.go +1 -1
  32. package/project/.sdk/tm/go/feature/secrets/plugin/env.go +1 -1
  33. package/project/.sdk/tm/go/feature/secrets/plugin/export.go +1 -1
  34. package/project/.sdk/tm/go/feature/secrets/plugin/graph.go +1 -1
  35. package/project/.sdk/tm/go/feature/secrets/plugin/host.go +1 -1
  36. package/project/.sdk/tm/go/feature/secrets/plugin/order.go +1 -1
  37. package/project/.sdk/tm/go/feature/secrets/plugin/point.go +1 -1
  38. package/project/.sdk/tm/go/feature/secrets/plugin/ref.go +1 -1
  39. package/project/.sdk/tm/go/feature/secrets/plugin/resolve.go +1 -1
  40. package/project/.sdk/tm/go/feature/secrets/plugin/types.go +1 -1
  41. package/project/.sdk/tm/go/feature/secrets/plugin/util.go +1 -1
  42. package/project/.sdk/tm/go/feature/secrets/plugin/version.go +1 -1
  43. package/project/.sdk/tm/go/feature/secrets/plugins/aws/aws.go +4 -4
  44. package/project/.sdk/tm/go/feature/secrets/plugins/aws/sigv4.go +2 -2
  45. package/project/.sdk/tm/go/feature/secrets/plugins/azuresecrets/azuresecrets.go +2 -2
  46. package/project/.sdk/tm/go/feature/secrets/plugins/boru/boru.go +2 -2
  47. package/project/.sdk/tm/go/feature/secrets/plugins/doppler/doppler.go +2 -2
  48. package/project/.sdk/tm/go/feature/secrets/plugins/gcpsecrets/gcpsecrets.go +2 -2
  49. package/project/.sdk/tm/go/feature/secrets/plugins/hashicorp/hashicorp.go +4 -5
  50. package/project/.sdk/tm/go/feature/secrets/plugins/httpjson/httpjson.go +3 -3
  51. package/project/.sdk/tm/go/feature/secrets/plugins/infisical/infisical.go +3 -4
  52. package/project/.sdk/tm/go/feature/secrets/plugins/onepassword/onepassword.go +2 -2
  53. package/project/.sdk/tm/go/feature/secrets/plugins/secretspec/secretspec.go +2 -2
  54. package/project/.sdk/tm/go/feature/secrets/sekreto/addr.go +2 -2
  55. package/project/.sdk/tm/go/feature/secrets/sekreto/providers.go +5 -2
  56. package/project/.sdk/tm/go/feature/secrets/sekreto/sekreto.go +31 -2
  57. package/project/.sdk/tm/go/test/omni/omni.go +8 -3
  58. package/project/.sdk/tm/go/test/omni/util.go +25 -4
  59. package/project/.sdk/tm/go/utility/struct/voxgigstruct.go +1 -1
  60. package/project/.sdk/tm/java/test/vendor/omni/Json.java +2 -2
  61. package/project/.sdk/tm/java/test/vendor/omni/Runner.java +2 -2
  62. package/project/.sdk/tm/java/test/vendor/omni/Util.java +2 -2
  63. package/project/.sdk/tm/java/utility/struct/Struct.java +1 -1
  64. package/project/.sdk/tm/js/src/utility/StructUtility.js +2 -2
  65. package/project/.sdk/tm/js/test/vendor/omni/index.js +1 -1
  66. package/project/.sdk/tm/js/test/vendor/omni/runner.js +18 -3
  67. package/project/.sdk/tm/js/test/vendor/omni/util.js +25 -8
  68. package/project/.sdk/tm/kotlin/test/vendor/omni/Json.kt +2 -2
  69. package/project/.sdk/tm/kotlin/test/vendor/omni/Runner.kt +2 -2
  70. package/project/.sdk/tm/kotlin/test/vendor/omni/Util.kt +2 -2
  71. package/project/.sdk/tm/kotlin/utility/struct/Struct.kt +1 -1
  72. package/project/.sdk/tm/lean/test/vendor/omni/Omni.lean +2 -2
  73. package/project/.sdk/tm/lua/test/vendor/omni/json.lua +2 -2
  74. package/project/.sdk/tm/lua/test/vendor/omni/regex.lua +2 -2
  75. package/project/.sdk/tm/lua/test/vendor/omni/runner.lua +2 -2
  76. package/project/.sdk/tm/lua/test/vendor/omni/util.lua +2 -2
  77. package/project/.sdk/tm/lua/utility/struct/regex.lua +1 -1
  78. package/project/.sdk/tm/lua/utility/struct/struct.lua +1 -1
  79. package/project/.sdk/tm/ocaml/test/vendor/omni/omni.ml +2 -2
  80. package/project/.sdk/tm/perl/lib/Voxgig/Struct.pm +1 -1
  81. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Runner.pm +1 -1
  82. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni/Util.pm +1 -1
  83. package/project/.sdk/tm/perl/t/vendor/omni/Voxgig/Omni.pm +1 -1
  84. package/project/.sdk/tm/php/test/vendor/omni/Runner.php +2 -2
  85. package/project/.sdk/tm/php/test/vendor/omni/Util.php +2 -2
  86. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/__init__.py +1 -1
  87. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/capability.py +1 -1
  88. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/catalog.py +1 -1
  89. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/config.py +1 -1
  90. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/depend.py +1 -1
  91. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/env.py +1 -1
  92. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/export.py +1 -1
  93. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/graph.py +1 -1
  94. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/host.py +1 -1
  95. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/order.py +1 -1
  96. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/point.py +1 -1
  97. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/ref.py +1 -1
  98. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/resolve.py +1 -1
  99. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/types.py +1 -1
  100. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_plugin/version.py +1 -1
  101. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/__init__.py +3 -1
  102. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/addr.py +1 -1
  103. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/aws.py +3 -3
  104. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/azuresecrets.py +1 -1
  105. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/boru.py +1 -1
  106. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/doppler.py +1 -1
  107. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/gcpsecrets.py +1 -1
  108. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/hashicorp.py +3 -4
  109. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/httpjson.py +1 -1
  110. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/infisical.py +4 -6
  111. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/onepassword.py +1 -1
  112. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/secretspec.py +1 -1
  113. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/plugins/sigv4.py +1 -1
  114. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/providers.py +1 -1
  115. package/project/.sdk/tm/py/pkg/feature/secrets/voxgig_sekreto/sekreto.py +21 -1
  116. package/project/.sdk/tm/py/pkg/utility/voxgig_struct/voxgig_struct.py +1 -1
  117. package/project/.sdk/tm/py/test/voxgig_omni/__init__.py +1 -1
  118. package/project/.sdk/tm/py/test/voxgig_omni/runner.py +16 -2
  119. package/project/.sdk/tm/py/test/voxgig_omni/util.py +27 -12
  120. package/project/.sdk/tm/rb/test/vendor/omni/runner.rb +2 -2
  121. package/project/.sdk/tm/rb/test/vendor/omni/util.rb +2 -2
  122. package/project/.sdk/tm/rb/test/vendor/omni/voxgig_omni.rb +2 -2
  123. package/project/.sdk/tm/rust/tests/vendor/omni/json.rs +2 -2
  124. package/project/.sdk/tm/rust/tests/vendor/omni/mod.rs +2 -2
  125. package/project/.sdk/tm/rust/tests/vendor/omni/regex.rs +2 -2
  126. package/project/.sdk/tm/rust/tests/vendor/omni/runner.rs +2 -2
  127. package/project/.sdk/tm/rust/tests/vendor/omni/util.rs +2 -2
  128. package/project/.sdk/tm/scala/sdktest/vendor/omni/Json.scala +2 -2
  129. package/project/.sdk/tm/scala/sdktest/vendor/omni/Runner.scala +2 -2
  130. package/project/.sdk/tm/scala/sdktest/vendor/omni/Util.scala +2 -2
  131. package/project/.sdk/tm/swift/Tests/vendor/omni/Json.swift +2 -2
  132. package/project/.sdk/tm/swift/Tests/vendor/omni/Runner.swift +2 -2
  133. package/project/.sdk/tm/swift/Tests/vendor/omni/Util.swift +2 -2
  134. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Capability.ts +1 -1
  135. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Catalog.ts +1 -1
  136. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Config.ts +1 -1
  137. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Depend.ts +1 -1
  138. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Env.ts +1 -1
  139. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Export.ts +1 -1
  140. package/project/.sdk/tm/ts/src/feature/secrets/plugin/FeatureHost.ts +1 -1
  141. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Graph.ts +1 -1
  142. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Host.ts +1 -1
  143. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Order.ts +1 -1
  144. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Point.ts +1 -1
  145. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Ref.ts +1 -1
  146. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Resolve.ts +1 -1
  147. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Types.ts +1 -1
  148. package/project/.sdk/tm/ts/src/feature/secrets/plugin/Version.ts +1 -1
  149. package/project/.sdk/tm/ts/src/feature/secrets/plugin/index.ts +1 -1
  150. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/Sekreto.ts +1 -1
  151. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/index.ts +1 -1
  152. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/aws.ts +1 -1
  153. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/azuresecrets.ts +1 -1
  154. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/boru.ts +1 -1
  155. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/doppler.ts +1 -1
  156. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/gcpsecrets.ts +1 -1
  157. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/hashicorp.ts +1 -1
  158. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/httpjson.ts +1 -1
  159. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/infisical.ts +1 -1
  160. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/onepassword.ts +1 -1
  161. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/secretspec.ts +1 -1
  162. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/plugins/sigv4.ts +1 -1
  163. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/addr.ts +1 -1
  164. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/builtin.ts +1 -1
  165. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/dotenv.ts +1 -1
  166. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/env.ts +1 -1
  167. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/file.ts +1 -1
  168. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/memory.ts +1 -1
  169. package/project/.sdk/tm/ts/src/feature/secrets/sekreto/provider/support.ts +1 -1
  170. package/project/.sdk/tm/ts/src/utility/StructUtility.ts +2 -2
  171. package/project/.sdk/tm/ts/test/vendor/omni/Runner.ts +1 -1
  172. package/project/.sdk/tm/ts/test/vendor/omni/Util.ts +1 -1
  173. package/project/.sdk/tm/ts/test/vendor/omni/index.ts +1 -1
  174. package/project/.sdk/tm/zig/Makefile +15 -1
  175. package/project/.sdk/tm/zig/build.zig +23 -5
  176. package/project/.sdk/tm/zig/core/helpers.zig +52 -11
  177. package/project/.sdk/tm/zig/core/mem.zig +17 -1
  178. package/project/.sdk/tm/zig/core/utility.zig +23 -19
  179. package/project/.sdk/tm/zig/feature/audit.zig +2 -2
  180. package/project/.sdk/tm/zig/feature/cache.zig +2 -2
  181. package/project/.sdk/tm/zig/feature/debug.zig +5 -5
  182. package/project/.sdk/tm/zig/feature/netsim.zig +2 -2
  183. package/project/.sdk/tm/zig/feature/paging.zig +2 -2
  184. package/project/.sdk/tm/zig/feature/proxy.zig +15 -8
  185. package/project/.sdk/tm/zig/feature/streaming.zig +5 -5
  186. package/project/.sdk/tm/zig/feature/support.zig +3 -3
  187. package/project/.sdk/tm/zig/feature/telemetry.zig +5 -5
  188. package/project/.sdk/tm/zig/feature/test.zig +10 -5
  189. package/project/.sdk/tm/zig/test/fh.zig +10 -10
  190. package/project/.sdk/tm/zig/test/gotcha_test.zig +5 -5
  191. package/project/.sdk/tm/zig/test/omniresolver.zig +515 -0
  192. package/project/.sdk/tm/zig/test/omnismoke_test.zig +284 -0
  193. package/project/.sdk/tm/zig/test/pipeline_test.zig +8 -8
  194. package/project/.sdk/tm/zig/test/primary_utility_test.zig +144 -154
  195. package/project/.sdk/tm/zig/test/struct_corpus.zig +264 -187
  196. package/project/.sdk/tm/zig/test/vendor/omni/omni.zig +1314 -0
  197. package/project/.sdk/tm/zig/test/vendor/omni/regex.zig +446 -0
  198. package/project/.sdk/tm/zig/utility/voxgigstruct/regex.zig +7 -4
  199. package/project/.sdk/tm/zig/utility/voxgigstruct/struct.zig +356 -157
  200. package/project/sdkgen-package.json +1 -1
  201. package/project/.sdk/tm/zig/test/struct_runner.zig +0 -465
@@ -0,0 +1,515 @@
1
+ // The corpus test runner: vendored @voxgig/omni driven through its NATIVE
2
+ // API (`omni.makeRunner` / `Runner.runner` / `RunPack.runsetflagsargs`, see
3
+ // test/vendor/omni/omni.zig - that file is the authority), presented to the
4
+ // corpus drivers in the subject shapes they already use. No compat shim is
5
+ // vendored: the adapter below IS the whole bridge, per language, per the
6
+ // vendor-tag rollout (docs/design/vendor-tag-rollout.md, Decision 4). It
7
+ // supersedes test/struct_runner.zig entirely - both its engine half
8
+ // (runset/runsetAlloc/runsetEntry) and its assertion half (matchval/doMatch
9
+ // /jsonEqual, subsumed by omni.matchval / omni.deepequal).
10
+ //
11
+ // NAMED omniresolver, NOT omni: the vendored module is imported as
12
+ // `@import("omni")`, and a resolver at test/omni.zig would make
13
+ // `@import("omni")` and `@import("omni.zig")` a one-character slip apart -
14
+ // with the wrong one still compiling, because both expose `matchval`,
15
+ // `NULLMARK` and a `RunPack`. The two names cannot be confused.
16
+ //
17
+ // Zig-specific decisions, each load-bearing:
18
+ //
19
+ // 1. TWO VALUE MODELS, CONVERTED AT THE SUBJECT BOUNDARY. omni speaks
20
+ // `std.json.Value`; the SDK and the corpus subjects speak the vendored
21
+ // struct port's `JsonValue`, whose containers are pointer-stable
22
+ // (*MapRef / *ListRef) because the struct API mutates through them. The
23
+ // retiring runner converted per entry (fromStdJson in, toStdJson out)
24
+ // and this keeps doing exactly that - there is no third model.
25
+ //
26
+ // 2. THE ARGUMENT IS WRITTEN BACK, so `match: {args: ...}` can be checked.
27
+ // `struct.minor.setpath` asserts on all seven entries that the subject
28
+ // rewrote the store it was handed, and `struct.merge.integrity` asserts
29
+ // on all six that merge did NOT. Conversion is a copy, so a mutation
30
+ // lands on the copy; the bridge therefore drives omni's `SubjectArgs`
31
+ // form and returns the converted-back argument alongside the result.
32
+ // The retiring runner could check neither: it ignored `match` outright.
33
+ //
34
+ // 3. A FAILURE IS A MESSAGE, NOT AN ERROR VALUE. Zig error values carry no
35
+ // payload, so `@errorName` gives the tag and never the text an `err`
36
+ // entry matches on. Every subject shape therefore reports failure
37
+ // through an `errout: *?[]const u8` out-parameter. The retiring runner
38
+ // SKIPPED every entry carrying `err` in the struct corpus (55 of them);
39
+ // they are checked now.
40
+ //
41
+ // 4. ZERO-ARGUMENT ENTRIES (`noval`). The corpus carries entries with no
42
+ // `in`, `args` or `ctx`, meaning "call the subject with NO argument".
43
+ // omni's native rule passes one JSON null. The vendored struct port has
44
+ // no NOVAL member in `JsonValue` - it cannot express absence as a value
45
+ // - so the port's own spelling of no-value is the UNDEFMARK string, and
46
+ // the corpus subjects (typify -> T_noval, clone -> null) already read
47
+ // it. `Flags.noval` rewrites such entries to `args: ["__UNDEF__"]`
48
+ // before the group runs, the same spec-rewrite go's resolver uses for
49
+ // its NOVAL sentinel. It is opt-in per group because the port answers
50
+ // correctly from a plain null everywhere else, and handing those groups
51
+ // a marker string would change what they test.
52
+ //
53
+ // 5. THE CTX PUBLISH SLOTS ARE PRE-CREATED IN `contextify`. The primary
54
+ // corpus asserts `match: {ctx: {spec|result|response: ...}}` on nine
55
+ // entries, and omni reads that from the `entry.ctx` it recorded BEFORE
56
+ // the call. In go or java that map is a reference and a subject just
57
+ // writes into it; `std.json.ObjectMap` is a VALUE (its length lives in
58
+ // the struct, not behind the pointer), so a key the subject ADDS is
59
+ // invisible to omni's copy while a key it OVERWRITES is shared. So
60
+ // `contextify` pre-creates the three publishable slots and the bridge
61
+ // writes back through `getPtr` - an in-place overwrite of an existing
62
+ // slot, which both copies see. The slots go into a FRESH map, never
63
+ // into the one omni handed over: see `contextify` for why growing that
64
+ // one faults the binary. Consequence, stated plainly: a ctx leaf
65
+ // asserted as `__EXISTS__` is satisfied by the pre-created null, so
66
+ // that ONE assertion shape (primary.makeRequest[0]) is weaker here than
67
+ // in a reference-semantics port. Every concrete ctx leaf is checked in
68
+ // full. The fix belongs upstream - a pointer-stable entry map in the
69
+ // zig port, or a runner that re-reads `ctx` from the returned args.
70
+ //
71
+ // 6. THE COUNT IS THE GUARD. A runner that stops executing looks exactly
72
+ // like a passing one, which is how two targets in this rollout went
73
+ // green while running nothing. So every group compares the number of
74
+ // SUBJECT INVOCATIONS against the number of entries the group declares,
75
+ // and refuses an empty set outright; `CASES`/`GROUPS` accumulate a
76
+ // census the suite asserts a floor on at the end.
77
+
78
+ const std = @import("std");
79
+ const omni = @import("omni");
80
+ const vs = @import("voxgig-struct");
81
+
82
+ const Allocator = std.mem.Allocator;
83
+
84
+ /// omni's value model.
85
+ pub const Json = omni.Json;
86
+
87
+ /// The SDK's and the corpus subjects' value model.
88
+ pub const JsonValue = vs.JsonValue;
89
+
90
+ pub const NULLMARK = omni.NULLMARK;
91
+ pub const UNDEFMARK = omni.UNDEFMARK;
92
+ pub const EXISTSMARK = omni.EXISTSMARK;
93
+
94
+ /// The shared corpus, compiled by the project build. Relative to the target
95
+ /// directory, which is where `zig build test` runs.
96
+ pub const TEST_JSON_FILE = "../.sdk/test/test.json";
97
+
98
+ /// The running census, across every group this test binary drove. A suite
99
+ /// asserts a floor on these at the end: a file whose test blocks were
100
+ /// deleted, or a runner that stopped executing, shows up as a number.
101
+ pub var CASES: usize = 0;
102
+ pub var GROUPS: usize = 0;
103
+
104
+ pub fn resetcensus() void {
105
+ CASES = 0;
106
+ GROUPS = 0;
107
+ }
108
+
109
+ // 0.16 reads files through an `std.Io` rather than free functions on
110
+ // `std.fs`. The corpus loader is test-only and has no Io of its own to
111
+ // thread through, so it uses the statically initialised singleton std
112
+ // itself falls back to.
113
+ fn testIo() std.Io {
114
+ return std.Io.Threaded.global_single_threaded.io();
115
+ }
116
+
117
+ /// The struct-corpus subject: one value in, one value out.
118
+ pub const Subject = *const fn (Allocator, JsonValue) JsonValue;
119
+
120
+ /// A subject that can FAIL with a message - `validate` and `transform`
121
+ /// answer `{out, err}`, and the corpus asserts on the text.
122
+ pub const FallibleSubject = *const fn (Allocator, JsonValue, *?[]const u8) JsonValue;
123
+
124
+ /// The primary-corpus subject: omni's own argument list (a contextified ctx
125
+ /// map, or the entry's `args`, or its `in`), the ctx view to publish back
126
+ /// for `match: {ctx: ...}`, and the SDK's own failure message.
127
+ pub const CtxSubject = *const fn (
128
+ alloc: Allocator,
129
+ args: []const Json,
130
+ published: *?Json,
131
+ errout: *?[]const u8,
132
+ ) anyerror!Json;
133
+
134
+ /// Per-group run options.
135
+ pub const Flags = struct {
136
+ /// omni's null flag: nulls (in the group AND in the result) normalise to
137
+ /// NULLMARK, and an entry with no `out` expects one. The canonical
138
+ /// per-group setting is the reference driver's
139
+ /// (tm/ts/test/utility/StructUtility.test.ts).
140
+ null_: bool = true,
141
+ /// An entry with no `in`/`args`/`ctx` reaches the subject as the port's
142
+ /// no-value marker rather than as one null. See decision 4.
143
+ noval: bool = false,
144
+ /// The label failures are reported under. Defaults to the runner's
145
+ /// section name, which is the same for every group in a suite.
146
+ name: ?[]const u8 = null,
147
+ };
148
+
149
+ const SubjectKind = union(enum) {
150
+ value: Subject,
151
+ fallible: FallibleSubject,
152
+ ctx: CtxSubject,
153
+ };
154
+
155
+ // Per-run state, reachable from omni's hooks through their `data` pointer
156
+ // (Zig has no closures; a hook is a bare function pointer plus this).
157
+ const Host = struct {
158
+ alloc: Allocator,
159
+ kind: ?SubjectKind = null,
160
+ calls: usize = 0,
161
+ };
162
+
163
+ /// The ctx facets a primary subject may publish. Pre-created by
164
+ /// `contextify` so the write-back below is an in-place overwrite - see
165
+ /// decision 5.
166
+ const CTX_SLOTS = [_][]const u8{ "spec", "result", "response" };
167
+
168
+ fn hostof(data: ?*const anyopaque) *Host {
169
+ return @ptrCast(@alignCast(@constCast(data.?)));
170
+ }
171
+
172
+ /// Hand the subject a ctx/args[0] map that already carries the publishable
173
+ /// slots (decision 5) - built as a COPY, leaving the map omni handed over
174
+ /// untouched.
175
+ ///
176
+ /// `std.json.ObjectMap` is unmanaged and by value, so growing a copy
177
+ /// reallocates the entries buffer and frees the old one, and every other
178
+ /// holder of the same struct keeps pointing into freed memory. omni is such
179
+ /// a holder: it installs this return value as `args[0]` and as `entry.ctx`,
180
+ /// but the entry's own `args` list still carries the map it was parsed with,
181
+ /// and `fail` stringifies exactly that when it reports a mismatch. Growing
182
+ /// in place therefore turned every FAILING case into a general protection
183
+ /// fault - the suite aborting instead of naming the entry that differed.
184
+ ///
185
+ /// Copying keeps both sides sound: the parsed map is never touched, and the
186
+ /// map omni holds after this returns IS the map the subject is called with,
187
+ /// so `publish`'s in-place `getPtr` overwrite is visible to both.
188
+ fn contextify(self: *const omni.Provider, val: Json) Json {
189
+ const host = hostof(self.data);
190
+ if (.object != val) {
191
+ return val;
192
+ }
193
+
194
+ var out: std.json.ObjectMap = .{};
195
+ var it = val.object.iterator();
196
+ while (it.next()) |field| {
197
+ out.put(host.alloc, field.key_ptr.*, field.value_ptr.*) catch return val;
198
+ }
199
+ for (CTX_SLOTS) |slot| {
200
+ if (!out.contains(slot)) {
201
+ out.put(host.alloc, slot, Json{ .null = {} }) catch return val;
202
+ }
203
+ }
204
+ return .{ .object = out };
205
+ }
206
+
207
+ /// Overwrite the pre-created ctx slots in place. Only keys that ALREADY
208
+ /// exist are written: adding one would be invisible to omni's own copy of
209
+ /// the map (decision 5), so a silent no-op is better than a silent lie.
210
+ fn publish(args: []const Json, view: Json) void {
211
+ if (0 == args.len or .object != args[0] or .object != view) {
212
+ return;
213
+ }
214
+
215
+ const target = args[0].object;
216
+ var it = view.object.iterator();
217
+ while (it.next()) |field| {
218
+ if (target.getPtr(field.key_ptr.*)) |slot| {
219
+ slot.* = field.value_ptr.*;
220
+ }
221
+ }
222
+ }
223
+
224
+ const OOM = "omniresolver: out of memory";
225
+
226
+ fn call(self: *const omni.SubjectArgs, args: []const Json) omni.SubjectArgsResult {
227
+ const host = hostof(self.data);
228
+ host.calls += 1;
229
+
230
+ const alloc = host.alloc;
231
+ const kind = host.kind orelse return .{ .err = "omniresolver: no subject" };
232
+
233
+ switch (kind) {
234
+ .ctx => |subject| {
235
+ var view: ?Json = null;
236
+ var errmsg: ?[]const u8 = null;
237
+ const res = subject(alloc, args, &view, &errmsg) catch |e| {
238
+ return .{ .err = errmsg orelse @errorName(e) };
239
+ };
240
+ if (errmsg) |message| {
241
+ return .{ .err = message };
242
+ }
243
+ if (view) |published| {
244
+ publish(args, published);
245
+ }
246
+ return .{ .ok = .{ .args = args, .res = res } };
247
+ },
248
+
249
+ .value, .fallible => {
250
+ const inarg: Json = if (0 < args.len) args[0] else Json{ .null = {} };
251
+ const inval = vs.fromStdJson(alloc, inarg) catch return .{ .err = OOM };
252
+
253
+ var errmsg: ?[]const u8 = null;
254
+ const out = switch (kind) {
255
+ .value => |subject| subject(alloc, inval),
256
+ .fallible => |subject| subject(alloc, inval, &errmsg),
257
+ else => unreachable,
258
+ };
259
+ if (errmsg) |message| {
260
+ return .{ .err = message };
261
+ }
262
+
263
+ const res = vs.toStdJson(alloc, out) catch return .{ .err = OOM };
264
+
265
+ // Decision 2: hand the (possibly mutated) argument back, so
266
+ // `match: {args: ...}` sees what the subject did with it.
267
+ const back = alloc.alloc(Json, args.len) catch return .{ .err = OOM };
268
+ @memcpy(back, args);
269
+ if (0 < back.len) {
270
+ back[0] = vs.toStdJson(alloc, inval) catch args[0];
271
+ }
272
+
273
+ return .{ .ok = .{ .args = back, .res = res } };
274
+ },
275
+ }
276
+ }
277
+
278
+ /// The number of entries a group declares, or null when it has no `set`.
279
+ pub fn setlen(group: omni.Maybe) ?usize {
280
+ const set = omni.jget(group, "set") orelse return null;
281
+ if (.array != set) {
282
+ return null;
283
+ }
284
+ return set.array.items.len;
285
+ }
286
+
287
+ /// Normalise a group's entries for this port, before omni sees it. Two
288
+ /// rewrites, both stated in the header:
289
+ ///
290
+ /// - `noval` (decision 4): an entry with no `in`, `args` or `ctx` carries the
291
+ /// port's no-value marker as its single argument.
292
+ ///
293
+ /// - THE ABSENT RESULT. With the null flag OFF, canonical omni leaves a
294
+ /// missing `out` ABSENT and a canonical port answers `undefined`, so the
295
+ /// two agree. The vendored struct port has no `undefined`: `JsonValue` can
296
+ /// express a null and nothing weaker, and omni-zig's own `fixjson` returns
297
+ /// `Json{.null}` for an absent value because its signature has nowhere to
298
+ /// put absence. So an entry that asserts "the subject answered nothing"
299
+ /// asserts a NULL here - written in as an explicit `out`, in the port's own
300
+ /// vocabulary. Only for an entry that asserts nothing else: one carrying
301
+ /// `err` or `match` is already checked through another path, and giving it
302
+ /// an `out` would add an assertion the corpus never made.
303
+ ///
304
+ /// Rebuilds the group; the loaded spec is never mutated.
305
+ fn prepare(alloc: Allocator, group: Json, flags: Flags) !Json {
306
+ if (flags.null_ and !flags.noval) {
307
+ return group;
308
+ }
309
+
310
+ const set = omni.jget(group, "set") orelse return group;
311
+ if (.array != set) {
312
+ return group;
313
+ }
314
+
315
+ var patched = std.json.Array.init(alloc);
316
+ for (set.array.items) |entry| {
317
+ if (.object != entry) {
318
+ try patched.append(entry);
319
+ continue;
320
+ }
321
+
322
+ const noargs = !omni.jhas(entry, "in") and
323
+ !omni.jhas(entry, "args") and !omni.jhas(entry, "ctx");
324
+ const wantnoval = flags.noval and noargs;
325
+ const wantnull = !flags.null_ and
326
+ !omni.jhas(entry, "out") and
327
+ !omni.jhas(entry, "err") and
328
+ !omni.jhas(entry, "match");
329
+
330
+ if (!wantnoval and !wantnull) {
331
+ try patched.append(entry);
332
+ continue;
333
+ }
334
+
335
+ var copy: std.json.ObjectMap = .{};
336
+ var it = entry.object.iterator();
337
+ while (it.next()) |field| {
338
+ try copy.put(alloc, field.key_ptr.*, field.value_ptr.*);
339
+ }
340
+ if (wantnoval) {
341
+ try copy.put(alloc, "args", try omni.jlist(alloc, &.{omni.jstr(UNDEFMARK)}));
342
+ }
343
+ if (wantnull) {
344
+ try copy.put(alloc, "out", Json{ .null = {} });
345
+ }
346
+ try patched.append(.{ .object = copy });
347
+ }
348
+
349
+ return omni.jset(alloc, group, "set", .{ .array = patched });
350
+ }
351
+
352
+ /// A loaded corpus section plus the provider that hosts the subjects.
353
+ pub const Runner = struct {
354
+ parent: Allocator,
355
+ arena: *std.heap.ArenaAllocator,
356
+ alloc: Allocator,
357
+ host: *Host,
358
+ provider: *omni.Provider,
359
+ inner: omni.Runner,
360
+ pack: omni.RunPack,
361
+
362
+ /// The message of the last failure, for the smoke test.
363
+ failure: ?[]const u8 = null,
364
+ /// Suppress the failure report (the smoke test EXPECTS failures).
365
+ quiet: bool = false,
366
+
367
+ pub fn deinit(self: *Runner) void {
368
+ const parent = self.parent;
369
+ const arena = self.arena;
370
+ arena.deinit();
371
+ parent.destroy(arena);
372
+ }
373
+
374
+ /// The resolved section, as loaded.
375
+ pub fn spec(self: *const Runner) Json {
376
+ return self.pack.spec;
377
+ }
378
+
379
+ /// A named group, one level down (`walk` -> `basic`). Absent when the
380
+ /// corpus does not carry it: the SDK corpus may omit a section the
381
+ /// upstream struct corpus has, and the corpus is the contract.
382
+ pub fn group(self: *const Runner, section: []const u8, name: []const u8) omni.Maybe {
383
+ return omni.jget(omni.jget(self.pack.spec, section), name);
384
+ }
385
+
386
+ /// A named group at the top of the section (`makeSpec` -> `basic`).
387
+ pub fn set(self: *const Runner, name: []const u8) omni.Maybe {
388
+ return omni.jget(self.pack.spec, name);
389
+ }
390
+
391
+ pub fn runset(self: *Runner, group_: omni.Maybe, subject: Subject) !void {
392
+ return self.drive(group_, .{}, .{ .value = subject });
393
+ }
394
+
395
+ pub fn runsetflags(self: *Runner, group_: omni.Maybe, flags: Flags, subject: Subject) !void {
396
+ return self.drive(group_, flags, .{ .value = subject });
397
+ }
398
+
399
+ pub fn runseterr(self: *Runner, group_: omni.Maybe, flags: Flags, subject: FallibleSubject) !void {
400
+ return self.drive(group_, flags, .{ .fallible = subject });
401
+ }
402
+
403
+ pub fn runsetctx(self: *Runner, group_: omni.Maybe, flags: Flags, subject: CtxSubject) !void {
404
+ return self.drive(group_, flags, .{ .ctx = subject });
405
+ }
406
+
407
+ fn drive(self: *Runner, group_: omni.Maybe, flags: Flags, kind: SubjectKind) !void {
408
+ self.failure = null;
409
+
410
+ // A group the corpus does not carry is a skip; a group it carries
411
+ // EMPTY is a failure. The lenient (version 0) spec format lets an
412
+ // empty set pass silently, and an emptied section is precisely the
413
+ // regression this rollout exists to catch.
414
+ const found = group_ orelse return error.SkipZigTest;
415
+ const declared = setlen(found) orelse {
416
+ self.report("omniresolver: group has no `set`", flags);
417
+ return error.NoTestSet;
418
+ };
419
+ if (0 == declared) {
420
+ self.report("omniresolver: empty test set", flags);
421
+ return error.EmptyTestSet;
422
+ }
423
+
424
+ const usegroup = try prepare(self.alloc, found, flags);
425
+
426
+ self.host.kind = kind;
427
+ self.host.calls = 0;
428
+
429
+ const argsubject = omni.SubjectArgs{ .call = call, .data = self.host };
430
+
431
+ const failure = try self.pack.runsetflagsargs(
432
+ usegroup,
433
+ .{ .null_ = flags.null_, .name = flags.name },
434
+ &argsubject,
435
+ );
436
+
437
+ if (failure) |message| {
438
+ self.failure = message;
439
+ if (!self.quiet) {
440
+ std.debug.print("\n{s}\n", .{message});
441
+ }
442
+ return error.CorpusFailure;
443
+ }
444
+
445
+ // Decision 6. omni returns on the FIRST failure, so this can only
446
+ // differ when the engine ran fewer entries than the group declares
447
+ // - a section that silently stopped driving the subject.
448
+ if (self.host.calls != declared) {
449
+ const message = std.fmt.allocPrint(
450
+ self.alloc,
451
+ "omniresolver: {s}: ran {d} of {d} declared cases",
452
+ .{ flags.name orelse self.pack.name, self.host.calls, declared },
453
+ ) catch "omniresolver: case count mismatch";
454
+ self.failure = message;
455
+ if (!self.quiet) {
456
+ std.debug.print("\n{s}\n", .{message});
457
+ }
458
+ return error.CasesNotRun;
459
+ }
460
+
461
+ CASES += self.host.calls;
462
+ GROUPS += 1;
463
+ }
464
+
465
+ fn report(self: *Runner, message: []const u8, flags: Flags) void {
466
+ self.failure = message;
467
+ if (!self.quiet) {
468
+ std.debug.print("\n{s}: {s}\n", .{ message, flags.name orelse self.pack.name });
469
+ }
470
+ }
471
+ };
472
+
473
+ fn build(parent: Allocator, section: []const u8, spec: ?Json) !Runner {
474
+ const arena = try parent.create(std.heap.ArenaAllocator);
475
+ errdefer parent.destroy(arena);
476
+ arena.* = std.heap.ArenaAllocator.init(parent);
477
+ errdefer arena.deinit();
478
+
479
+ const alloc = arena.allocator();
480
+
481
+ const host = try alloc.create(Host);
482
+ host.* = .{ .alloc = alloc };
483
+
484
+ const provider = try alloc.create(omni.Provider);
485
+ provider.* = .{ .contextify = contextify, .data = host };
486
+
487
+ const inner = if (spec) |value|
488
+ try omni.makeRunnerSpec(alloc, value, provider)
489
+ else
490
+ try omni.makeRunner(alloc, testIo(), TEST_JSON_FILE, provider);
491
+
492
+ const pack = try inner.runner(section, null);
493
+
494
+ return .{
495
+ .parent = parent,
496
+ .arena = arena,
497
+ .alloc = alloc,
498
+ .host = host,
499
+ .provider = provider,
500
+ .inner = inner,
501
+ .pack = pack,
502
+ };
503
+ }
504
+
505
+ /// A runner over the shared corpus file, resolved at one named section
506
+ /// ("struct", "primary").
507
+ pub fn makeRunner(parent: Allocator, section: []const u8) !Runner {
508
+ return build(parent, section, null);
509
+ }
510
+
511
+ /// A runner over an in-memory spec (omni's own capability), which keeps the
512
+ /// smoke test free of fixture files.
513
+ pub fn makeRunnerSpec(parent: Allocator, spec: Json, section: []const u8) !Runner {
514
+ return build(parent, section, spec);
515
+ }