hecks 3.14.0 → 4.0.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 (419) hide show
  1. checksums.yaml +4 -4
  2. data/examples/pizzas/adapters/fake_processor.rb +34 -0
  3. data/examples/pizzas/adapters/payment_signature.rb +66 -0
  4. data/examples/pizzas/adapters/payment_webhook.rb +87 -0
  5. data/examples/pizzas/bluebook/pizzas.behaviors +33 -0
  6. data/examples/pizzas/bluebook/pizzas.hecksagon +5 -3
  7. data/examples/pizzas/config.ru +22 -0
  8. data/lib/hecks/adapters/driven/prism.rb +0 -2
  9. data/lib/hecks/adapters/driven.rb +0 -2
  10. data/lib/hecks/adapters/driving/json.rb +1 -7
  11. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -2
  12. data/lib/hecks/bluebook/dsl/derivation_words.rb +58 -0
  13. data/lib/hecks/bluebook/dsl/translation_builder.rb +6 -37
  14. data/lib/hecks/bluebook/expression/ast_json.rb +0 -9
  15. data/lib/hecks/bluebook/hecksagon.rb +1 -1
  16. data/lib/hecks/bluebook/meta_validator/translation_judge/rules.rb +7 -10
  17. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +4 -8
  18. data/lib/hecks/bluebook/meta_validator.rb +0 -11
  19. data/lib/hecks/bluebook/translation.rb +18 -10
  20. data/lib/hecks/bluebook/translation_expression/evaluator.rb +63 -0
  21. data/lib/hecks/bluebook/translation_expression/parser.rb +127 -0
  22. data/lib/hecks/bluebook/translation_expression.rb +39 -0
  23. data/lib/hecks/bluebook/translation_plan.rb +70 -0
  24. data/lib/hecks/bluebook.rb +2 -0
  25. data/lib/hecks/chapters.rb +3 -3
  26. data/lib/hecks/composer/adapters/claude_composer.adapter +3 -0
  27. data/lib/hecks/composer/adapters/claude_composer.rb +83 -0
  28. data/lib/hecks/composer/adapters/fake_agent.adapter +3 -0
  29. data/lib/hecks/composer/adapters/fake_agent.rb +55 -0
  30. data/lib/hecks/composer/adapters/jev.adapter +3 -0
  31. data/lib/hecks/composer/adapters/jev.rb +66 -0
  32. data/lib/hecks/composer/agent.rb +113 -0
  33. data/lib/hecks/composer/assistant.rb +110 -0
  34. data/lib/hecks/composer/behavior_run.rb +53 -0
  35. data/lib/hecks/composer/bluebook/composer.bluebook +178 -0
  36. data/lib/hecks/composer/bluebook/composer.hecksagon +16 -0
  37. data/lib/hecks/composer/board.rb +65 -0
  38. data/lib/hecks/composer/board_edit/command_text.rb +39 -0
  39. data/lib/hecks/composer/board_edit/source.rb +84 -0
  40. data/lib/hecks/composer/board_edit.rb +144 -0
  41. data/lib/hecks/composer/check.rb +89 -0
  42. data/lib/hecks/composer/domains.rb +81 -0
  43. data/lib/hecks/composer/jobs.rb +134 -0
  44. data/lib/hecks/composer/layout.rb +37 -0
  45. data/lib/hecks/composer/live.rb +150 -0
  46. data/lib/hecks/composer/outline.rb +48 -0
  47. data/lib/hecks/composer/page.html +989 -0
  48. data/lib/hecks/composer/panels.rb +142 -0
  49. data/lib/hecks/composer/parse.rb +83 -0
  50. data/lib/hecks/composer/plain.rb +28 -0
  51. data/lib/hecks/composer/ports/composer_agent.port +7 -0
  52. data/lib/hecks/composer/session.rb +141 -0
  53. data/lib/hecks/composer/toolbox.rb +166 -0
  54. data/lib/hecks/composer/web.rb +156 -0
  55. data/lib/hecks/composer/workbench.rb +51 -0
  56. data/lib/hecks/composer/workspace.rb +81 -0
  57. data/lib/hecks/composer.rb +17 -0
  58. data/lib/hecks/corpus/adapters.rb +22 -0
  59. data/lib/hecks/corpus/rust.rb +1 -1
  60. data/lib/hecks/corpus/worlds.rb +19 -0
  61. data/lib/hecks/corpus.rb +5 -0
  62. data/lib/hecks/forms/app/commands.rb +2 -3
  63. data/lib/hecks/forms/app/queries.rb +2 -3
  64. data/lib/hecks/forms/app/records.rb +17 -5
  65. data/lib/hecks/forms/command_form_renderer.rb +42 -16
  66. data/lib/hecks/forms/field_controls.rb +2 -2
  67. data/lib/hecks/forms/field_renderer.rb +1 -1
  68. data/lib/hecks/forms/field_shape.rb +36 -17
  69. data/lib/hecks/forms/index_renderer.rb +2 -1
  70. data/lib/hecks/forms/page.rb +1 -1
  71. data/lib/hecks/forms/params.rb +0 -13
  72. data/lib/hecks/forms/query_form_renderer.rb +7 -6
  73. data/lib/hecks/forms/record_renderer.rb +11 -7
  74. data/lib/hecks/forms/rule_words.rb +100 -0
  75. data/lib/hecks/forms/value_object_shape.rb +2 -1
  76. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -3
  77. data/lib/hecks/fuzzing/isolated_boot/worlds.rb +3 -6
  78. data/lib/hecks/fuzzing/replay/filters.rb +2 -6
  79. data/lib/hecks/gate/stages.yml +25 -0
  80. data/lib/hecks/grammar/evolve/seeds.rb +0 -6
  81. data/lib/hecks/grammar/evolve.rb +0 -3
  82. data/lib/hecks/grammar/translation.bluebook +1 -1
  83. data/lib/hecks/hecks/adapters/codebase/composing.rb +56 -0
  84. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +3 -1
  85. data/lib/hecks/hecks/adapters/journal_store/changes.rb +0 -26
  86. data/lib/hecks/hecks/adapters/journal_store/examination.rb +2 -23
  87. data/lib/hecks/hecks/adapters/journal_store/readings.rb +3 -11
  88. data/lib/hecks/hecks/adapters/journal_store.rb +0 -11
  89. data/lib/hecks/hecks/adapters/rehearsal/inquiry.rb +4 -11
  90. data/lib/hecks/hecks/adapters/rehearsal/memory_store.rb +0 -9
  91. data/lib/hecks/hecks/adapters/rehearsal/postgres_reading.rb +0 -4
  92. data/lib/hecks/hecks/codebase.behaviors +6 -0
  93. data/lib/hecks/hecks/codebase.bluebook +21 -0
  94. data/lib/hecks/hecks/composer.behaviors +68 -0
  95. data/lib/hecks/hecks/context_map.hecksagon +1 -1
  96. data/lib/hecks/hecks/custodian.behaviors +0 -6
  97. data/lib/hecks/hecks/custodian.bluebook +3 -80
  98. data/lib/hecks/hecks/hecks.hecksagon +2 -2
  99. data/lib/hecks/hecks/hecks.world +1 -1
  100. data/lib/hecks/hecks/rehearsal.bluebook +7 -13
  101. data/lib/hecks/kernel_capabilities/templates.rb +4 -4
  102. data/lib/hecks/kernel_capabilities.rb +1 -1
  103. data/lib/hecks/language/bluebook/vocabulary.bluebook +2 -3
  104. data/lib/hecks/language/translation/translation_aggregate.bluebook +21 -24
  105. data/lib/hecks/ports/access_control.rb +2 -2
  106. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -41
  107. data/lib/hecks/ports/persistence/plugins/era/lineage/coverage.rb +7 -7
  108. data/lib/hecks/ports/persistence/plugins/era/lineage/rewrite.rb +25 -2
  109. data/lib/hecks/ports/persistence/plugins/era/lineage/rules.rb +4 -4
  110. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +17 -25
  111. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/base_sql.rb +0 -12
  112. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/domain_rename.rb +1 -1
  113. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -22
  114. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +0 -1
  115. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +9 -3
  116. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +3 -29
  117. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/refusals.rb +2 -26
  118. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +6 -33
  119. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -3
  120. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +2 -4
  121. data/lib/hecks/ports/persistence/plugins/era/translation/expression_sql.rb +52 -0
  122. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +23 -29
  123. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +1 -1
  124. data/lib/hecks/ports/persistence/plugins/era/translation.rb +0 -1
  125. data/lib/hecks/ports/persistence/plugins/era.rb +3 -6
  126. data/lib/hecks/ports.rb +0 -1
  127. data/lib/hecks/projection_files.rb +3 -1
  128. data/lib/hecks/projections/deploy/templates/lambda/nat_comment_oauth.tmpl +1 -1
  129. data/lib/hecks/projections/glossary/entries.rb +10 -4
  130. data/lib/hecks/projections/glossary/groups.rb +42 -0
  131. data/lib/hecks/projections/glossary/html/page.rb +7 -2
  132. data/lib/hecks/projections/glossary/html/parser.rb +1 -1
  133. data/lib/hecks/projections/glossary/html/sections.rb +31 -11
  134. data/lib/hecks/projections/glossary/html.rb +1 -2
  135. data/lib/hecks/projections/glossary/markdown.rb +31 -28
  136. data/lib/hecks/projections/glossary/mermaid.rb +3 -0
  137. data/lib/hecks/projections/glossary/page.css +143 -153
  138. data/lib/hecks/projections/glossary/page.js +63 -3
  139. data/lib/hecks/projections/glossary/sentences/actions.rb +88 -0
  140. data/lib/hecks/projections/glossary/sentences/paths.rb +77 -0
  141. data/lib/hecks/projections/glossary/sentences/queries.rb +90 -0
  142. data/lib/hecks/projections/glossary/sentences/value_objects.rb +32 -5
  143. data/lib/hecks/projections/glossary/sentences.rb +13 -3
  144. data/lib/hecks/projections/glossary/slugs.rb +4 -1
  145. data/lib/hecks/projections/glossary.rb +2 -1
  146. data/lib/hecks/projections/plain_english.rb +97 -0
  147. data/lib/hecks/projections/rust_vocabulary/arguments.rb +2 -2
  148. data/lib/hecks/projections/rust_vocabulary/enum_body.rb +20 -25
  149. data/lib/hecks/projections/rust_vocabulary/tests.rb +2 -2
  150. data/lib/hecks/projections/rust_vocabulary.rb +14 -6
  151. data/lib/hecks/projections/site/cms_editor/color.rb +0 -6
  152. data/lib/hecks/projections/statements/actions.rb +99 -0
  153. data/lib/hecks/projections/statements/relationships.rb +86 -0
  154. data/lib/hecks/projections/statements.rb +15 -24
  155. data/lib/hecks/projector/exporter/adapters.rb +112 -0
  156. data/lib/hecks/projector/exporter/translations.rb +18 -35
  157. data/lib/hecks/projector/exporter/worlds.rb +103 -0
  158. data/lib/hecks/projector/exporter.rb +5 -1
  159. data/lib/hecks/quality_control/adapters/agent.rb +6 -7
  160. data/lib/hecks/quality_control/adapters/agent_profile.rb +16 -114
  161. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +1 -1
  162. data/lib/hecks/runtime/loader/boot_steps.rb +0 -20
  163. data/lib/hecks/runtime/outbox.rb +2 -9
  164. data/lib/hecks/runtime/port_operation_interpreter.rb +1 -9
  165. data/lib/hecks/runtime/remote_dispatcher.rb +2 -2
  166. data/lib/hecks/runtime/value.rb +13 -0
  167. data/lib/hecks/rust_build/project_rust/target_ir.rb +23 -4
  168. data/lib/hecks/rust_build/wasm.rb +0 -12
  169. data/lib/hecks/rust_build/write_if_changed.rb +12 -12
  170. data/lib/hecks/rust_format.rb +77 -0
  171. data/lib/hecks/tools/fuzz_sweep/findings.rb +3 -9
  172. data/lib/hecks/tools/fuzz_sweep.rb +1 -3
  173. data/lib/hecks/tools/translation_audit/verdicts.rb +3 -28
  174. data/lib/hecks/tools/translation_audit.rb +8 -10
  175. data/lib/hecks/tools/translation_scaffold/reporting.rb +1 -1
  176. data/lib/hecks/version.rb +1 -1
  177. data/lib/hecks/vocabulary.rb +2 -1
  178. data/lib/hecks.rb +3 -0
  179. data/prebuilt/{a883a7e568667aa5ac904c82daff356bdf9e996252a36af6def4a4a43efb967e.marshal → 02c09c73b272c1fb5a9ae6d87bb5e5e529208e00f6b4b597dc2c0fd70a9c0964.marshal} +0 -0
  180. data/prebuilt/{1a6f596be124228be93eba1d86dbc9d2933190fa389b284331241cb9f27115a0.marshal → bb84a835cf6a15136bad5ca03aa5bf93a5b92f5f72444618d3ef2412b987fb32.marshal} +0 -0
  181. data/prebuilt/{verdicts-872993b1aa26d73fe48f28251374b8585fed145d02aab42be0f00de386b6ff80.json → verdicts-f1f10da14c8e8f01b4c9b7e3e2d74be8cd2bf4676364ed17fa16975d2a076d75.json} +1 -1
  182. data/rust/Cargo.toml +40 -0
  183. data/rust/build/Cargo.toml +36 -0
  184. data/rust/build/clippy.toml +4 -0
  185. data/rust/build/src/adapters_pass.rs +196 -0
  186. data/rust/build/src/binding_pass.rs +54 -13
  187. data/rust/build/src/build_artifact.rs +23 -5
  188. data/rust/build/src/cargo_sync.rs +69 -26
  189. data/rust/build/src/lineage_pass.rs +101 -87
  190. data/rust/build/src/main.rs +11 -2
  191. data/rust/build/src/pipeline.rs +80 -19
  192. data/rust/build/src/reserved_names.rs +6 -50
  193. data/rust/build/src/resolve.rs +82 -35
  194. data/rust/build/src/rustfmt.rs +100 -0
  195. data/rust/build/src/seams_pass.rs +85 -16
  196. data/rust/build/src/subprocess.rs +30 -6
  197. data/rust/build/src/tmp.rs +5 -2
  198. data/rust/build/src/translation_pass.rs +72 -22
  199. data/rust/build/src/world_pass.rs +109 -0
  200. data/rust/clippy.toml +4 -0
  201. data/rust/codegen/Cargo.toml +36 -0
  202. data/rust/codegen/clippy.toml +4 -0
  203. data/rust/codegen/src/asks.rs +40 -14
  204. data/rust/codegen/src/attr.rs +2 -2
  205. data/rust/codegen/src/bridging.rs +676 -117
  206. data/rust/codegen/src/commands.rs +979 -373
  207. data/rust/codegen/src/constraints.rs +88 -25
  208. data/rust/codegen/src/dependency_planning.rs +128 -34
  209. data/rust/codegen/src/domain_generator.rs +300 -170
  210. data/rust/codegen/src/exemplar.rs +87 -32
  211. data/rust/codegen/src/expr_emitter.rs +54 -6
  212. data/rust/codegen/src/fielded.rs +193 -41
  213. data/rust/codegen/src/hecks_naming.rs +124 -16
  214. data/rust/codegen/src/hecks_naming_tests.rs +81 -0
  215. data/rust/codegen/src/json.rs +80 -44
  216. data/rust/codegen/src/json_codec.rs +585 -149
  217. data/rust/codegen/src/literal.rs +104 -138
  218. data/rust/codegen/src/main.rs +145 -52
  219. data/rust/codegen/src/manifest.rs +76 -14
  220. data/rust/codegen/src/mutations.rs +1212 -239
  221. data/rust/codegen/src/naming.rs +111 -60
  222. data/rust/codegen/src/optional_pass.rs +90 -28
  223. data/rust/codegen/src/ports.rs +5 -4
  224. data/rust/codegen/src/prelude.rs +139 -49
  225. data/rust/codegen/src/queries.rs +601 -226
  226. data/rust/codegen/src/reactions.rs +268 -74
  227. data/rust/codegen/src/read_models.rs +606 -205
  228. data/rust/codegen/src/reference_specs.rs +16 -3
  229. data/rust/codegen/src/registry.rs +128 -79
  230. data/rust/codegen/src/reserved_names.rs +6 -50
  231. data/rust/codegen/src/shared.rs +71 -22
  232. data/rust/codegen/src/sidecars.rs +15 -5
  233. data/rust/codegen/src/skip_reason.rs +8 -2
  234. data/rust/codegen/src/types.rs +306 -108
  235. data/rust/host/Cargo.lock +1 -0
  236. data/rust/host/Cargo.toml +40 -4
  237. data/rust/host/HECKS_RELEASE +1 -1
  238. data/rust/host/clippy.toml +4 -0
  239. data/rust/host/src/api.rs +698 -218
  240. data/rust/host/src/auth.rs +491 -214
  241. data/rust/host/src/b64.rs +91 -0
  242. data/rust/host/src/bin/expr_harness.rs +6 -2
  243. data/rust/host/src/bin/lineage_harness.rs +47 -11
  244. data/rust/host/src/bin/mint_harness.rs +70 -37
  245. data/rust/host/src/bin/validate_harness.rs +16 -8
  246. data/rust/host/src/boot.rs +144 -68
  247. data/rust/host/src/boundary_fuzz/api.rs +130 -32
  248. data/rust/host/src/boundary_fuzz/auth.rs +108 -23
  249. data/rust/host/src/boundary_fuzz/expr_json.rs +85 -11
  250. data/rust/host/src/boundary_fuzz/ir.rs +164 -12
  251. data/rust/host/src/boundary_fuzz/server.rs +283 -36
  252. data/rust/host/src/boundary_fuzz/web.rs +56 -8
  253. data/rust/host/src/checkout.rs +78 -32
  254. data/rust/host/src/clock.rs +8 -0
  255. data/rust/host/src/commerce_ir.rs +333 -95
  256. data/rust/host/src/crypto.rs +33 -0
  257. data/rust/host/src/dispatch.rs +990 -331
  258. data/rust/host/src/expr_json.rs +1021 -273
  259. data/rust/host/src/extension.rs +24 -4
  260. data/rust/host/src/field_hints.rs +11 -7
  261. data/rust/host/src/fuzz_support.rs +85 -13
  262. data/rust/host/src/host.rs +100 -0
  263. data/rust/host/src/http.rs +22 -0
  264. data/rust/host/src/ir.rs +326 -16
  265. data/rust/host/src/journal.rs +277 -176
  266. data/rust/host/src/lambda_client.rs +219 -53
  267. data/rust/host/src/lib.rs +16 -4
  268. data/rust/host/src/log.rs +62 -11
  269. data/rust/host/src/mint.rs +1153 -326
  270. data/rust/host/src/needs.rs +185 -44
  271. data/rust/host/src/payments/keystore.rs +197 -45
  272. data/rust/host/src/payments/roles.rs +39 -7
  273. data/rust/host/src/payments/tests.rs +1427 -282
  274. data/rust/host/src/payments.rs +391 -112
  275. data/rust/host/src/platform_signin/attack_tests.rs +5 -5
  276. data/rust/host/src/platform_signin/config.rs +11 -11
  277. data/rust/host/src/platform_signin/cookie.rs +2 -2
  278. data/rust/host/src/platform_signin/extension.rs +2 -1
  279. data/rust/host/src/platform_signin/handler.rs +9 -8
  280. data/rust/host/src/platform_signin/jti.rs +4 -2
  281. data/rust/host/src/platform_signin/jwks.rs +2 -1
  282. data/rust/host/src/platform_signin/jws.rs +2 -37
  283. data/rust/host/src/platform_signin/known_answer_tests.rs +5 -1
  284. data/rust/host/src/platform_signin/mode_tests.rs +5 -3
  285. data/rust/host/src/platform_signin/pages.rs +20 -20
  286. data/rust/host/src/platform_signin/session.rs +8 -1
  287. data/rust/host/src/platform_signin/settings.rs +6 -6
  288. data/rust/host/src/platform_signin/strict_json.rs +12 -9
  289. data/rust/host/src/platform_signin/verify.rs +41 -41
  290. data/rust/host/src/platform_signin/wiring_support.rs +13 -18
  291. data/rust/host/src/presentation.rs +207 -63
  292. data/rust/host/src/presentation_write.rs +502 -187
  293. data/rust/host/src/query_step.rs +69 -18
  294. data/rust/host/src/rate_limit.rs +541 -142
  295. data/rust/host/src/reference_transform.rs +77 -25
  296. data/rust/host/src/reference_validate.rs +443 -104
  297. data/rust/host/src/resend.rs +190 -55
  298. data/rust/host/src/secrets.rs +116 -21
  299. data/rust/host/src/server.rs +483 -104
  300. data/rust/host/src/storage_shape.rs +88 -21
  301. data/rust/host/src/test_pg.rs +17 -7
  302. data/rust/host/src/ui_schema.rs +495 -207
  303. data/rust/host/src/wasm_runner.rs +21 -6
  304. data/rust/host/src/web/commerce.rs +101 -23
  305. data/rust/host/src/web/newsletter/cooldown.rs +10 -3
  306. data/rust/host/src/web/newsletter/template.rs +26 -7
  307. data/rust/host/src/web/newsletter/tests.rs +112 -23
  308. data/rust/host/src/web/newsletter.rs +209 -59
  309. data/rust/host/src/web/newsletter_send.rs +251 -79
  310. data/rust/host/src/web/registration_receipt/tests.rs +16 -4
  311. data/rust/host/src/web/registration_receipt.rs +100 -24
  312. data/rust/host/src/web/registrations.rs +1384 -332
  313. data/rust/host/src/web/resend_webhook.rs +138 -80
  314. data/rust/host/src/web.rs +2416 -508
  315. data/rust/lsp/Cargo.toml +36 -0
  316. data/rust/lsp/clippy.toml +4 -0
  317. data/rust/lsp/src/json.rs +29 -22
  318. data/rust/lsp/src/main.rs +81 -31
  319. data/rust/lsp/src/outline.rs +23 -7
  320. data/rust/lsp/src/rpc.rs +17 -4
  321. data/rust/parser/Cargo.toml +36 -0
  322. data/rust/parser/clippy.toml +4 -0
  323. data/rust/parser/src/build/closed_sets.rs +6 -1
  324. data/rust/parser/src/build/identity.rs +4 -3
  325. data/rust/parser/src/build/mod.rs +1 -1
  326. data/rust/parser/src/build/named_pattern.rs +4 -1
  327. data/rust/parser/src/build/naming.rs +2 -80
  328. data/rust/parser/src/build/pattern_subset.rs +6 -8
  329. data/rust/parser/src/build/query_derive.rs +3 -1
  330. data/rust/parser/src/build/query_inference.rs +14 -5
  331. data/rust/parser/src/build/read_model.rs +4 -1
  332. data/rust/parser/src/build/references.rs +4 -3
  333. data/rust/parser/src/canonical.rs +34 -15
  334. data/rust/parser/src/emit.rs +187 -105
  335. data/rust/parser/src/expr/ast_json.rs +134 -42
  336. data/rust/parser/src/expr/evaluator.rs +27 -9
  337. data/rust/parser/src/expr/mod.rs +54 -13
  338. data/rust/parser/src/expr/resolver.rs +299 -92
  339. data/rust/parser/src/ir.rs +35 -3
  340. data/rust/parser/src/keywords.rs +7168 -516
  341. data/rust/parser/src/lex.rs +11 -25
  342. data/rust/parser/src/lib.rs +1 -0
  343. data/rust/parser/src/main.rs +65 -6
  344. data/rust/parser/src/parse/adapter.rs +157 -0
  345. data/rust/parser/src/parse/aggregate.rs +19 -10
  346. data/rust/parser/src/parse/chapter.rs +16 -17
  347. data/rust/parser/src/parse/command.rs +35 -16
  348. data/rust/parser/src/parse/domain_port.rs +4 -7
  349. data/rust/parser/src/parse/entity.rs +21 -11
  350. data/rust/parser/src/parse/hecksagon.rs +10 -4
  351. data/rust/parser/src/parse/lifecycle.rs +9 -5
  352. data/rust/parser/src/parse/mod.rs +22 -91
  353. data/rust/parser/src/parse/needs.rs +21 -12
  354. data/rust/parser/src/parse/policy.rs +2 -2
  355. data/rust/parser/src/parse/process_manager.rs +9 -11
  356. data/rust/parser/src/parse/query.rs +8 -4
  357. data/rust/parser/src/parse/read_model.rs +57 -16
  358. data/rust/parser/src/parse/value_object.rs +7 -2
  359. data/rust/parser/src/parse/world.rs +322 -0
  360. data/rust/parser/src/ruby_value.rs +7 -6
  361. data/rust/src/exemplar/json.rs +4 -4
  362. data/rust/src/exemplar/mutations.rs +18 -0
  363. data/rust/src/exemplar/read_models.rs +1 -10
  364. data/rust/src/kernel/attribute_shapes/composite.rs +54 -14
  365. data/rust/src/kernel/attribute_shapes/list.rs +2 -2
  366. data/rust/src/kernel/attribute_shapes/mod.rs +8 -8
  367. data/rust/src/kernel/attribute_shapes/scalar.rs +2 -2
  368. data/rust/src/kernel/cli.rs +229 -112
  369. data/rust/src/kernel/dispatch.rs +323 -115
  370. data/rust/src/kernel/dispatch_guard_tests.rs +327 -65
  371. data/rust/src/kernel/expr.rs +203 -86
  372. data/rust/src/kernel/expression_operators/arithmetic.rs +138 -25
  373. data/rust/src/kernel/expression_operators/comparison.rs +87 -2
  374. data/rust/src/kernel/expression_operators/enumeration.rs +106 -22
  375. data/rust/src/kernel/expression_operators/logical.rs +9 -3
  376. data/rust/src/kernel/expression_operators/membership.rs +3 -1
  377. data/rust/src/kernel/expression_operators/mod.rs +34 -21
  378. data/rust/src/kernel/expression_operators/pattern_match.rs +46 -11
  379. data/rust/src/kernel/expression_operators/positional.rs +84 -30
  380. data/rust/src/kernel/expression_operators/presence.rs +52 -13
  381. data/rust/src/kernel/expression_operators/sign_test.rs +3 -1
  382. data/rust/src/kernel/expression_operators/sized.rs +24 -8
  383. data/rust/src/kernel/expression_operators/text.rs +120 -27
  384. data/rust/src/kernel/expression_operators/to_string.rs +10 -4
  385. data/rust/src/kernel/json.rs +230 -148
  386. data/rust/src/kernel/mod.rs +46 -33
  387. data/rust/src/kernel/named_query.rs +63 -15
  388. data/rust/src/kernel/needs.rs +112 -25
  389. data/rust/src/kernel/orchestrate.rs +980 -581
  390. data/rust/src/kernel/orchestrate_guard_tests.rs +538 -140
  391. data/rust/src/kernel/pattern.rs +107 -34
  392. data/rust/src/kernel/query_comparators.rs +118 -41
  393. data/rust/src/kernel/query_ordering.rs +13 -5
  394. data/rust/src/kernel/read_model.rs +479 -181
  395. data/rust/src/kernel/reference_lookup.rs +122 -26
  396. data/rust/src/kernel/repository.rs +293 -66
  397. data/rust/src/kernel/routing.rs +58 -42
  398. data/rust/src/kernel/ruby_float.rs +139 -0
  399. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +57 -57
  400. data/rust/src/kernel/vocab/entity_dispatch_order.rs +54 -54
  401. data/rust/src/kernel/vocab/field_hint.rs +19 -25
  402. data/rust/src/kernel/vocab/mod.rs +6 -6
  403. data/rust/src/kernel/vocab/query_comparator.rs +23 -24
  404. data/rust/src/kernel/vocab/refusal_template.rs +501 -297
  405. data/rust/src/lib.rs +50 -0
  406. data/rust/src/main.rs +4 -1
  407. data/rust/web/Cargo.toml +36 -0
  408. data/rust/web/clippy.toml +4 -0
  409. metadata +82 -15
  410. data/examples/pizzas/bluebook/hecksagon/mock_stripe_payment_adapter.rb +0 -36
  411. data/lib/hecks/adapters/driven/google_authentication.adapter +0 -3
  412. data/lib/hecks/adapters/driven/google_authentication.rb +0 -99
  413. data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +0 -3
  414. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +0 -32
  415. data/lib/hecks/ports/authentication.port +0 -6
  416. data/lib/hecks/ports/authentication.rb +0 -67
  417. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +0 -255
  418. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +0 -22
  419. data/rust/host/src/approval.rs +0 -652
@@ -102,6 +102,16 @@ impl RoutingEnvelope {
102
102
  }
103
103
  }
104
104
 
105
+ /// Step-envelope keys (`verb`, `role`, ...) are not facts, so `with:` may sit beside them.
106
+ const STEP_ENVELOPE_KEYS: [&str; 6] = [
107
+ "verb",
108
+ "role",
109
+ "actor_id",
110
+ "occurred_at",
111
+ "dry_run",
112
+ "query",
113
+ ];
114
+
105
115
  #[derive(Debug, Clone, PartialEq)]
106
116
  pub struct CommandInvocation {
107
117
  route: Option<RoutingEnvelope>,
@@ -121,15 +131,14 @@ impl CommandInvocation {
121
131
  /// The facts source depends on `with:` alone, never on `to:`.
122
132
  pub fn from_json(value: &Json) -> Result<Self, Refusal> {
123
133
  let target = non_null(value.get("to"));
124
- let explicit_facts = non_null(value.get("with"));
125
- if explicit_facts.is_none() {
134
+ let Some(explicit_facts) = non_null(value.get("with")) else {
126
135
  let route = target.map(RoutingEnvelope::from_json).transpose()?;
127
136
  return Ok(Self {
128
137
  route,
129
138
  facts: strip_routing_keys(value),
130
139
  explicit: false,
131
140
  });
132
- }
141
+ };
133
142
 
134
143
  if value.get("args").is_some() {
135
144
  return Err(routing_refusal("cannot combine to/with with legacy args"));
@@ -137,42 +146,40 @@ impl CommandInvocation {
137
146
 
138
147
  // `with:` beside a loose fact is refused, as Ruby's `Routing.payload` refuses it.
139
148
  // Step-envelope keys (`verb`, `role`, ...) are not facts and are exempt.
140
- const STEP_ENVELOPE_KEYS: [&str; 6] =
141
- ["verb", "role", "actor_id", "occurred_at", "dry_run", "query"];
142
- if explicit_facts.is_some() {
143
- if let Json::Object(fields) = value {
144
- let extra = fields
145
- .iter()
146
- .any(|(key, _)| key != "to" && key != "with" && !STEP_ENVELOPE_KEYS.contains(&key.as_str()));
147
- if extra {
148
- return Err(routing_refusal(
149
- "with: takes command facts, not both with: and loose keyword arguments",
150
- ));
151
- }
149
+ if let Json::Object(fields) = value {
150
+ let extra = fields.iter().any(|(key, _)| {
151
+ key != "to" && key != "with" && !STEP_ENVELOPE_KEYS.contains(&key.as_str())
152
+ });
153
+ if extra {
154
+ return Err(routing_refusal(
155
+ "with: takes command facts, not both with: and loose keyword arguments",
156
+ ));
152
157
  }
153
158
  }
154
159
 
155
160
  let route = target.map(RoutingEnvelope::from_json).transpose()?;
156
- let facts = explicit_facts
157
- .cloned()
158
- .expect("explicit_facts checked Some above");
161
+ let facts = explicit_facts.clone();
159
162
  if !matches!(facts, Json::Object(_)) {
160
163
  return Err(routing_refusal("with must be an object of command facts"));
161
164
  }
162
165
 
163
- Ok(Self { route, facts, explicit: true })
166
+ Ok(Self {
167
+ route,
168
+ facts,
169
+ explicit: true,
170
+ })
164
171
  }
165
172
 
166
- pub fn route(&self) -> Option<&RoutingEnvelope> {
173
+ pub const fn route(&self) -> Option<&RoutingEnvelope> {
167
174
  self.route.as_ref()
168
175
  }
169
176
 
170
- pub fn facts(&self) -> &Json {
177
+ pub const fn facts(&self) -> &Json {
171
178
  &self.facts
172
179
  }
173
180
 
174
181
  /// True when this call used the explicit `with:` shape, false for flat facts.
175
- pub fn explicit_with(&self) -> bool {
182
+ pub const fn explicit_with(&self) -> bool {
176
183
  self.explicit
177
184
  }
178
185
 
@@ -358,21 +365,24 @@ mod tests {
358
365
  assert_eq!(invocation.route(), None);
359
366
  assert_eq!(
360
367
  invocation.facts(),
361
- &Json::obj(vec![("name", Json::obj(vec![("value", Json::str("golf"))]))])
368
+ &Json::obj(vec![(
369
+ "name",
370
+ Json::obj(vec![("value", Json::str("golf"))])
371
+ )])
362
372
  );
363
373
  }
364
374
 
365
375
  // Same for a null `with`: read as the no-`to:` shape; the null key is dropped from the facts.
366
376
  #[test]
367
377
  fn null_with_and_no_to_key_is_read_as_legacy_shape_not_explicit_facts() {
368
- let input = Json::obj(vec![
369
- ("with", Json::Null),
370
- ("amount", Json::int(20)),
371
- ]);
378
+ let input = Json::obj(vec![("with", Json::Null), ("amount", Json::int(20))]);
372
379
 
373
380
  let invocation = CommandInvocation::from_json(&input).unwrap();
374
381
  assert_eq!(invocation.route(), None);
375
- assert_eq!(invocation.facts(), &Json::obj(vec![("amount", Json::int(20))]));
382
+ assert_eq!(
383
+ invocation.facts(),
384
+ &Json::obj(vec![("amount", Json::int(20))])
385
+ );
376
386
  }
377
387
 
378
388
  // A non-null `to` is always parsed as a route, even when a domain fact is named `to`.
@@ -381,7 +391,9 @@ mod tests {
381
391
  let input = Json::obj(vec![("to", Json::obj(vec![("value", Json::int(282))]))]);
382
392
 
383
393
  let err = CommandInvocation::from_json(&input).unwrap_err();
384
- assert!(err.to_string().contains("entity route requires a scalar aggregate identity"));
394
+ assert!(err
395
+ .to_string()
396
+ .contains("entity route requires a scalar aggregate identity"));
385
397
  }
386
398
 
387
399
  // A real `to:` with flat facts and no `with:` must keep the facts; only `with:` selects them.
@@ -396,7 +408,10 @@ mod tests {
396
408
  let route = invocation.route().unwrap();
397
409
  route.require_depth(0).unwrap();
398
410
  assert_eq!(route.aggregate(), "ORDER-7");
399
- assert_eq!(invocation.facts(), &Json::obj(vec![("quantity", Json::int(3))]));
411
+ assert_eq!(
412
+ invocation.facts(),
413
+ &Json::obj(vec![("quantity", Json::int(3))])
414
+ );
400
415
  }
401
416
 
402
417
  // Same, with an entity route as `to:`.
@@ -427,14 +442,14 @@ mod tests {
427
442
  // Same, with `to: null` beside real facts.
428
443
  #[test]
429
444
  fn null_to_alongside_real_facts_keeps_the_flat_facts() {
430
- let input = Json::obj(vec![
431
- ("to", Json::Null),
432
- ("quantity", Json::int(3)),
433
- ]);
445
+ let input = Json::obj(vec![("to", Json::Null), ("quantity", Json::int(3))]);
434
446
 
435
447
  let invocation = CommandInvocation::from_json(&input).unwrap();
436
448
  assert_eq!(invocation.route(), None);
437
- assert_eq!(invocation.facts(), &Json::obj(vec![("quantity", Json::int(3))]));
449
+ assert_eq!(
450
+ invocation.facts(),
451
+ &Json::obj(vec![("quantity", Json::int(3))])
452
+ );
438
453
  }
439
454
 
440
455
  // `explicit_with()` is true only when the explicit `with:` branch was taken.
@@ -461,11 +476,8 @@ mod tests {
461
476
  .unwrap();
462
477
  assert!(!legacy_with_to.explicit_with());
463
478
 
464
- let legacy_no_to = CommandInvocation::from_json(&Json::obj(vec![(
465
- "amount",
466
- Json::int(20),
467
- )]))
468
- .unwrap();
479
+ let legacy_no_to =
480
+ CommandInvocation::from_json(&Json::obj(vec![("amount", Json::int(20))])).unwrap();
469
481
  assert!(!legacy_no_to.explicit_with());
470
482
 
471
483
  let legacy_null_with = CommandInvocation::from_json(&Json::obj(vec![
@@ -499,7 +511,9 @@ mod tests {
499
511
  ),
500
512
  ]))
501
513
  .unwrap();
502
- let (receiver, facts) = explicit.split_aggregate_receiver(Some("order"), None).unwrap();
514
+ let (receiver, facts) = explicit
515
+ .split_aggregate_receiver(Some("order"), None)
516
+ .unwrap();
503
517
  assert_eq!(receiver, "ORDER-7");
504
518
  assert_eq!(facts, Json::obj(vec![("amount", Json::int(20))]));
505
519
 
@@ -508,7 +522,9 @@ mod tests {
508
522
  ("amount", Json::int(30)),
509
523
  ]))
510
524
  .unwrap();
511
- let (receiver, facts) = legacy.split_aggregate_receiver(Some("order"), None).unwrap();
525
+ let (receiver, facts) = legacy
526
+ .split_aggregate_receiver(Some("order"), None)
527
+ .unwrap();
512
528
  assert_eq!(receiver, "ORDER-8");
513
529
  assert_eq!(facts, Json::obj(vec![("amount", Json::int(30))]));
514
530
 
@@ -0,0 +1,139 @@
1
+ //! Ruby-style `Float#to_s` and the finite-result check shared by float arithmetic.
2
+ //!
3
+ //! Fault wording quotes operands the way Ruby prints them (`1.0e+308`, not Rust's 309-digit
4
+ //! expansion), so a Fault from either runtime reads the same.
5
+
6
+ use crate::kernel::Refusal;
7
+
8
+ // Ruby switches to scientific notation when the decimal point sits left of 1e-4 or right of 1e16.
9
+ const FIXED_MIN_EXPONENT: i32 = -4;
10
+ const FIXED_MAX_EXPONENT: i32 = 15;
11
+
12
+ /// `Float#to_s`: shortest round-trip digits, fixed notation for `1e-4 <= |n| < 1e16`, else `d.ddde+XX`.
13
+ pub fn to_s(n: f64) -> String {
14
+ if n.is_nan() {
15
+ return "NaN".to_string();
16
+ }
17
+ if n.is_infinite() {
18
+ return if n < 0.0 { "-Infinity" } else { "Infinity" }.to_string();
19
+ }
20
+ let sign = if n.is_sign_negative() { "-" } else { "" };
21
+ if n == 0.0 {
22
+ return format!("{sign}0.0");
23
+ }
24
+ // `{:e}` yields the shortest round-trip digits as `d.ddde<exp>`.
25
+ let scientific = format!("{:e}", n.abs());
26
+ let (mantissa, exponent) = scientific.split_once('e').unwrap_or((&scientific, "0"));
27
+ let exponent: i32 = exponent.parse().unwrap_or(0);
28
+ let digits: String = mantissa.chars().filter(char::is_ascii_digit).collect();
29
+ if (FIXED_MIN_EXPONENT..=FIXED_MAX_EXPONENT).contains(&exponent) {
30
+ return format!("{sign}{}", fixed(&digits, exponent));
31
+ }
32
+ let (head, tail) = digits.split_at(1);
33
+ let tail = if tail.is_empty() { "0" } else { tail };
34
+ let exponent_sign = if exponent < 0 { '-' } else { '+' };
35
+ format!("{sign}{head}.{tail}e{exponent_sign}{:02}", exponent.abs())
36
+ }
37
+
38
+ // Places the decimal point `exponent` digits after the first digit, padding zeros as needed.
39
+ fn fixed(digits: &str, exponent: i32) -> String {
40
+ if exponent < 0 {
41
+ let zeros = "0".repeat(exponent.unsigned_abs() as usize - 1);
42
+ return format!("0.{zeros}{digits}");
43
+ }
44
+ let whole_len = exponent as usize + 1;
45
+ if digits.len() <= whole_len {
46
+ let zeros = "0".repeat(whole_len - digits.len());
47
+ return format!("{digits}{zeros}.0");
48
+ }
49
+ let (whole, fraction) = digits.split_at(whole_len);
50
+ format!("{whole}.{fraction}")
51
+ }
52
+
53
+ /// Passes a float arithmetic `result` through only if finite; else the C3.4 Fault.
54
+ ///
55
+ /// Ruby quotes the right operand by absolute value, so a decrement still reads `a - |b|`.
56
+ pub fn finite_or_fault(
57
+ op: &str,
58
+ symbol: &str,
59
+ lhs: f64,
60
+ rhs: f64,
61
+ result: f64,
62
+ ) -> Result<f64, Refusal> {
63
+ if result.is_finite() {
64
+ return Ok(result);
65
+ }
66
+ Err(Refusal::Fault(format!(
67
+ "{op} overflowed: {} {symbol} {} is not a finite number",
68
+ to_s(lhs),
69
+ to_s(rhs.abs())
70
+ )))
71
+ }
72
+
73
+ #[cfg(test)]
74
+ mod tests {
75
+ use super::*;
76
+
77
+ #[test]
78
+ fn whole_numbers_keep_a_decimal_point() {
79
+ assert_eq!(to_s(1.0), "1.0");
80
+ assert_eq!(to_s(-250.0), "-250.0");
81
+ assert_eq!(to_s(0.0), "0.0");
82
+ }
83
+
84
+ #[test]
85
+ fn fractions_print_shortest_round_trip_digits() {
86
+ assert_eq!(to_s(0.1), "0.1");
87
+ assert_eq!(to_s(1.5), "1.5");
88
+ assert_eq!(to_s(0.0001), "0.0001");
89
+ assert_eq!(to_s(123_456.789), "123456.789");
90
+ }
91
+
92
+ #[test]
93
+ fn large_magnitudes_switch_to_scientific_at_1e16() {
94
+ assert_eq!(to_s(1.0e15), "1000000000000000.0");
95
+ assert_eq!(to_s(1.0e16), "1.0e+16");
96
+ assert_eq!(to_s(1.0e308), "1.0e+308");
97
+ assert_eq!(to_s(1.5e20), "1.5e+20");
98
+ }
99
+
100
+ #[test]
101
+ fn small_magnitudes_switch_to_scientific_below_1e_4() {
102
+ assert_eq!(to_s(0.00001), "1.0e-05");
103
+ assert_eq!(to_s(1.25e-7), "1.25e-07");
104
+ }
105
+
106
+ #[test]
107
+ fn non_finite_values_use_rubys_names() {
108
+ assert_eq!(to_s(f64::INFINITY), "Infinity");
109
+ assert_eq!(to_s(f64::NEG_INFINITY), "-Infinity");
110
+ assert_eq!(to_s(f64::NAN), "NaN");
111
+ }
112
+
113
+ #[test]
114
+ fn an_infinite_result_faults_with_rubys_wording() {
115
+ let fault = finite_or_fault("increment", "+", 1.0e308, 1.0e308, f64::INFINITY);
116
+ assert_eq!(
117
+ fault,
118
+ Err(Refusal::Fault(
119
+ "increment overflowed: 1.0e+308 + 1.0e+308 is not a finite number".to_string()
120
+ ))
121
+ );
122
+ }
123
+
124
+ #[test]
125
+ fn a_decrement_quotes_the_amount_by_absolute_value() {
126
+ let fault = finite_or_fault("decrement", "-", -1.0e308, -1.0e308, f64::NEG_INFINITY);
127
+ assert_eq!(
128
+ fault,
129
+ Err(Refusal::Fault(
130
+ "decrement overflowed: -1.0e+308 - 1.0e+308 is not a finite number".to_string()
131
+ ))
132
+ );
133
+ }
134
+
135
+ #[test]
136
+ fn a_finite_result_passes_through() {
137
+ assert_eq!(finite_or_fault("multiply", "*", 2.0, 3.0, 6.0), Ok(6.0));
138
+ }
139
+ }
@@ -26,74 +26,74 @@ pub enum AggregateStep {
26
26
 
27
27
  impl AggregateStep {
28
28
  /// The declared step order, first to last.
29
- pub const ORDER: [AggregateStep; 17] = [
30
- AggregateStep::DecodeArguments,
31
- AggregateStep::RefuseUnknownArguments,
32
- AggregateStep::RefuseAbsentArguments,
33
- AggregateStep::NormalizeArgs,
34
- AggregateStep::RefuseRoleMismatch,
35
- AggregateStep::ResolveReferences,
36
- AggregateStep::Hydrate,
37
- AggregateStep::EnforceGivens,
38
- AggregateStep::AdmissibleTransition,
39
- AggregateStep::AssignCreationAttributes,
40
- AggregateStep::ApplyMutations,
41
- AggregateStep::AdvanceLifecycle,
42
- AggregateStep::DelegateToEntity,
43
- AggregateStep::EnforceEnsures,
44
- AggregateStep::EnforceInvariants,
45
- AggregateStep::Save,
46
- AggregateStep::Emit,
29
+ pub const ORDER: [Self; 17] = [
30
+ Self::DecodeArguments,
31
+ Self::RefuseUnknownArguments,
32
+ Self::RefuseAbsentArguments,
33
+ Self::NormalizeArgs,
34
+ Self::RefuseRoleMismatch,
35
+ Self::ResolveReferences,
36
+ Self::Hydrate,
37
+ Self::EnforceGivens,
38
+ Self::AdmissibleTransition,
39
+ Self::AssignCreationAttributes,
40
+ Self::ApplyMutations,
41
+ Self::AdvanceLifecycle,
42
+ Self::DelegateToEntity,
43
+ Self::EnforceEnsures,
44
+ Self::EnforceInvariants,
45
+ Self::Save,
46
+ Self::Emit,
47
47
  ];
48
48
 
49
49
  /// The row's declared `step`.
50
- pub fn step(&self) -> &'static str {
50
+ pub const fn step(&self) -> &'static str {
51
51
  match self {
52
- AggregateStep::DecodeArguments => "decode_arguments",
53
- AggregateStep::RefuseUnknownArguments => "refuse_unknown_arguments",
54
- AggregateStep::RefuseAbsentArguments => "refuse_absent_arguments",
55
- AggregateStep::NormalizeArgs => "normalize_args",
56
- AggregateStep::RefuseRoleMismatch => "refuse_role_mismatch",
57
- AggregateStep::ResolveReferences => "resolve_references",
58
- AggregateStep::Hydrate => "hydrate",
59
- AggregateStep::EnforceGivens => "enforce_givens",
60
- AggregateStep::AdmissibleTransition => "admissible_transition",
61
- AggregateStep::AssignCreationAttributes => "assign_creation_attributes",
62
- AggregateStep::ApplyMutations => "apply_mutations",
63
- AggregateStep::AdvanceLifecycle => "advance_lifecycle",
64
- AggregateStep::DelegateToEntity => "delegate_to_entity",
65
- AggregateStep::EnforceEnsures => "enforce_ensures",
66
- AggregateStep::EnforceInvariants => "enforce_invariants",
67
- AggregateStep::Save => "save",
68
- AggregateStep::Emit => "emit",
52
+ Self::DecodeArguments => "decode_arguments",
53
+ Self::RefuseUnknownArguments => "refuse_unknown_arguments",
54
+ Self::RefuseAbsentArguments => "refuse_absent_arguments",
55
+ Self::NormalizeArgs => "normalize_args",
56
+ Self::RefuseRoleMismatch => "refuse_role_mismatch",
57
+ Self::ResolveReferences => "resolve_references",
58
+ Self::Hydrate => "hydrate",
59
+ Self::EnforceGivens => "enforce_givens",
60
+ Self::AdmissibleTransition => "admissible_transition",
61
+ Self::AssignCreationAttributes => "assign_creation_attributes",
62
+ Self::ApplyMutations => "apply_mutations",
63
+ Self::AdvanceLifecycle => "advance_lifecycle",
64
+ Self::DelegateToEntity => "delegate_to_entity",
65
+ Self::EnforceEnsures => "enforce_ensures",
66
+ Self::EnforceInvariants => "enforce_invariants",
67
+ Self::Save => "save",
68
+ Self::Emit => "emit",
69
69
  }
70
70
  }
71
71
 
72
72
  /// The row whose `step` is `name`, if any.
73
- pub fn from_name(name: &str) -> Option<AggregateStep> {
74
- AggregateStep::ORDER.iter().copied().find(|row| row.step() == name)
73
+ pub fn from_name(name: &str) -> Option<Self> {
74
+ Self::ORDER.iter().copied().find(|row| row.step() == name)
75
75
  }
76
76
 
77
77
  /// This step's index in `ORDER`.
78
- pub fn position(&self) -> usize {
78
+ pub const fn position(&self) -> usize {
79
79
  match self {
80
- AggregateStep::DecodeArguments => 0,
81
- AggregateStep::RefuseUnknownArguments => 1,
82
- AggregateStep::RefuseAbsentArguments => 2,
83
- AggregateStep::NormalizeArgs => 3,
84
- AggregateStep::RefuseRoleMismatch => 4,
85
- AggregateStep::ResolveReferences => 5,
86
- AggregateStep::Hydrate => 6,
87
- AggregateStep::EnforceGivens => 7,
88
- AggregateStep::AdmissibleTransition => 8,
89
- AggregateStep::AssignCreationAttributes => 9,
90
- AggregateStep::ApplyMutations => 10,
91
- AggregateStep::AdvanceLifecycle => 11,
92
- AggregateStep::DelegateToEntity => 12,
93
- AggregateStep::EnforceEnsures => 13,
94
- AggregateStep::EnforceInvariants => 14,
95
- AggregateStep::Save => 15,
96
- AggregateStep::Emit => 16,
80
+ Self::DecodeArguments => 0,
81
+ Self::RefuseUnknownArguments => 1,
82
+ Self::RefuseAbsentArguments => 2,
83
+ Self::NormalizeArgs => 3,
84
+ Self::RefuseRoleMismatch => 4,
85
+ Self::ResolveReferences => 5,
86
+ Self::Hydrate => 6,
87
+ Self::EnforceGivens => 7,
88
+ Self::AdmissibleTransition => 8,
89
+ Self::AssignCreationAttributes => 9,
90
+ Self::ApplyMutations => 10,
91
+ Self::AdvanceLifecycle => 11,
92
+ Self::DelegateToEntity => 12,
93
+ Self::EnforceEnsures => 13,
94
+ Self::EnforceInvariants => 14,
95
+ Self::Save => 15,
96
+ Self::Emit => 16,
97
97
  }
98
98
  }
99
99
  }
@@ -104,7 +104,7 @@ mod tests {
104
104
 
105
105
  #[test]
106
106
  fn every_row_is_found_by_its_own_name() {
107
- for row in AggregateStep::ORDER.iter() {
107
+ for row in &AggregateStep::ORDER {
108
108
  assert_eq!(AggregateStep::from_name(row.step()), Some(*row));
109
109
  }
110
110
  }
@@ -25,71 +25,71 @@ pub enum EntityStep {
25
25
 
26
26
  impl EntityStep {
27
27
  /// The declared step order, first to last.
28
- pub const ORDER: [EntityStep; 16] = [
29
- EntityStep::DecodeArguments,
30
- EntityStep::RefuseUnknownArguments,
31
- EntityStep::RefuseAbsentArguments,
32
- EntityStep::NormalizeArgs,
33
- EntityStep::RefuseRoleMismatch,
34
- EntityStep::ResolveReferences,
35
- EntityStep::HydrateParent,
36
- EntityStep::LocateElement,
37
- EntityStep::EnforceGivens,
38
- EntityStep::AdmissibleTransition,
39
- EntityStep::ApplyMutations,
40
- EntityStep::AdvanceLifecycle,
41
- EntityStep::EnforceEnsures,
42
- EntityStep::EnforceInvariants,
43
- EntityStep::Save,
44
- EntityStep::Emit,
28
+ pub const ORDER: [Self; 16] = [
29
+ Self::DecodeArguments,
30
+ Self::RefuseUnknownArguments,
31
+ Self::RefuseAbsentArguments,
32
+ Self::NormalizeArgs,
33
+ Self::RefuseRoleMismatch,
34
+ Self::ResolveReferences,
35
+ Self::HydrateParent,
36
+ Self::LocateElement,
37
+ Self::EnforceGivens,
38
+ Self::AdmissibleTransition,
39
+ Self::ApplyMutations,
40
+ Self::AdvanceLifecycle,
41
+ Self::EnforceEnsures,
42
+ Self::EnforceInvariants,
43
+ Self::Save,
44
+ Self::Emit,
45
45
  ];
46
46
 
47
47
  /// The row's declared `step`.
48
- pub fn step(&self) -> &'static str {
48
+ pub const fn step(&self) -> &'static str {
49
49
  match self {
50
- EntityStep::DecodeArguments => "decode_arguments",
51
- EntityStep::RefuseUnknownArguments => "refuse_unknown_arguments",
52
- EntityStep::RefuseAbsentArguments => "refuse_absent_arguments",
53
- EntityStep::NormalizeArgs => "normalize_args",
54
- EntityStep::RefuseRoleMismatch => "refuse_role_mismatch",
55
- EntityStep::ResolveReferences => "resolve_references",
56
- EntityStep::HydrateParent => "hydrate_parent",
57
- EntityStep::LocateElement => "locate_element",
58
- EntityStep::EnforceGivens => "enforce_givens",
59
- EntityStep::AdmissibleTransition => "admissible_transition",
60
- EntityStep::ApplyMutations => "apply_mutations",
61
- EntityStep::AdvanceLifecycle => "advance_lifecycle",
62
- EntityStep::EnforceEnsures => "enforce_ensures",
63
- EntityStep::EnforceInvariants => "enforce_invariants",
64
- EntityStep::Save => "save",
65
- EntityStep::Emit => "emit",
50
+ Self::DecodeArguments => "decode_arguments",
51
+ Self::RefuseUnknownArguments => "refuse_unknown_arguments",
52
+ Self::RefuseAbsentArguments => "refuse_absent_arguments",
53
+ Self::NormalizeArgs => "normalize_args",
54
+ Self::RefuseRoleMismatch => "refuse_role_mismatch",
55
+ Self::ResolveReferences => "resolve_references",
56
+ Self::HydrateParent => "hydrate_parent",
57
+ Self::LocateElement => "locate_element",
58
+ Self::EnforceGivens => "enforce_givens",
59
+ Self::AdmissibleTransition => "admissible_transition",
60
+ Self::ApplyMutations => "apply_mutations",
61
+ Self::AdvanceLifecycle => "advance_lifecycle",
62
+ Self::EnforceEnsures => "enforce_ensures",
63
+ Self::EnforceInvariants => "enforce_invariants",
64
+ Self::Save => "save",
65
+ Self::Emit => "emit",
66
66
  }
67
67
  }
68
68
 
69
69
  /// The row whose `step` is `name`, if any.
70
- pub fn from_name(name: &str) -> Option<EntityStep> {
71
- EntityStep::ORDER.iter().copied().find(|row| row.step() == name)
70
+ pub fn from_name(name: &str) -> Option<Self> {
71
+ Self::ORDER.iter().copied().find(|row| row.step() == name)
72
72
  }
73
73
 
74
74
  /// This step's index in `ORDER`.
75
- pub fn position(&self) -> usize {
75
+ pub const fn position(&self) -> usize {
76
76
  match self {
77
- EntityStep::DecodeArguments => 0,
78
- EntityStep::RefuseUnknownArguments => 1,
79
- EntityStep::RefuseAbsentArguments => 2,
80
- EntityStep::NormalizeArgs => 3,
81
- EntityStep::RefuseRoleMismatch => 4,
82
- EntityStep::ResolveReferences => 5,
83
- EntityStep::HydrateParent => 6,
84
- EntityStep::LocateElement => 7,
85
- EntityStep::EnforceGivens => 8,
86
- EntityStep::AdmissibleTransition => 9,
87
- EntityStep::ApplyMutations => 10,
88
- EntityStep::AdvanceLifecycle => 11,
89
- EntityStep::EnforceEnsures => 12,
90
- EntityStep::EnforceInvariants => 13,
91
- EntityStep::Save => 14,
92
- EntityStep::Emit => 15,
77
+ Self::DecodeArguments => 0,
78
+ Self::RefuseUnknownArguments => 1,
79
+ Self::RefuseAbsentArguments => 2,
80
+ Self::NormalizeArgs => 3,
81
+ Self::RefuseRoleMismatch => 4,
82
+ Self::ResolveReferences => 5,
83
+ Self::HydrateParent => 6,
84
+ Self::LocateElement => 7,
85
+ Self::EnforceGivens => 8,
86
+ Self::AdmissibleTransition => 9,
87
+ Self::ApplyMutations => 10,
88
+ Self::AdvanceLifecycle => 11,
89
+ Self::EnforceEnsures => 12,
90
+ Self::EnforceInvariants => 13,
91
+ Self::Save => 14,
92
+ Self::Emit => 15,
93
93
  }
94
94
  }
95
95
  }
@@ -100,7 +100,7 @@ mod tests {
100
100
 
101
101
  #[test]
102
102
  fn every_row_is_found_by_its_own_name() {
103
- for row in EntityStep::ORDER.iter() {
103
+ for row in &EntityStep::ORDER {
104
104
  assert_eq!(EntityStep::from_name(row.step()), Some(*row));
105
105
  }
106
106
  }