gen_types/dispatcher.rs
1//! `TypedDispatcher` — introspection trait every typed-variant
2//! enum implements via `#[derive(TypedDispatcher)]` in gen-macros.
3//!
4//! Surface the variant universe (kebab-case serde tags + per-variant
5//! field names) so the substrate can mechanically:
6//!
7//! - emit the matching Nix `helpers = { ... }` table skeleton
8//! (one entry per variant);
9//! - render a Lisp catalog entry naming the dispatcher;
10//! - generate a coverage test that fails when a variant has no
11//! consumer arm.
12//!
13//! Trait-only — no runtime dispatch. Rust enums already dispatch
14//! natively via `match`; this trait is the *catalog reflection*
15//! that exposes the same enum to other runtimes (Nix, Lisp) so they
16//! can build dispatch tables against it.
17//!
18//! ## Naming
19//!
20//! "Dispatcher" emphasises the catamorphism the trait participates
21//! in. See `theory/QUIRK-APPLIER.md` §IV-bis for the full leverage
22//! scope — every typed variant universe at a language boundary is a
23//! candidate `TypedDispatcher`.
24
25/// Reflection over a typed variant universe — typically a Rust enum
26/// declaring `#[serde(tag = "kind", rename_all = "kebab-case")]`.
27pub trait TypedDispatcher {
28 /// Kebab-case serde tags of every variant in declaration order.
29 /// Used by substrate emitters (Nix helpers skeleton, Lisp catalog,
30 /// coverage tests) to enumerate the variant universe.
31 fn variant_kinds() -> Vec<&'static str>;
32
33 /// Field names per variant, paired with the variant's kebab-case
34 /// tag. Used by substrate emitters to produce the matching
35 /// `inherit (variant) <fields>` Nix patterns.
36 fn variant_fields() -> Vec<(&'static str, Vec<&'static str>)>;
37
38 /// Total variant count. Convenience for coverage assertions.
39 #[must_use]
40 fn variant_count() -> usize {
41 Self::variant_kinds().len()
42 }
43}