gen_platform/lib.rs
1//! `gen-platform` — Rust-first canonical handle for the typed-
2//! dispatcher substrate primitive (typed-tagged-union catamorphism
3//! at a language boundary). Re-exports `TypedDispatcher` +
4//! `#[derive(TypedDispatcher)]`, ships a runtime `Dispatcher<T>`
5//! applicator for Rust consumers (controllers, daemons, reactive
6//! routers, migration runners, RBAC engines, render passes), and
7//! surfaces typed catalog primitives so any pleme-io crate can
8//! stand up a typed dispatch surface against any closed variant
9//! universe with one cargo add.
10//!
11//! ## Why a dedicated crate
12//!
13//! The `mk-typed-dispatcher.nix` primitive proves the value at the
14//! Nix dispatch layer. The same shape recurs across pleme-io
15//! wherever a closed variant set drives an action (see
16//! [`theory/QUIRK-APPLIER.md`](https://github.com/pleme-io/theory/blob/main/QUIRK-APPLIER.md)
17//! §IV-bis.1 for the catalog). `gen-platform` is the canonical
18//! Rust-side handle so consumers in pangea-operator, engenho
19//! controllers, magma plan walkers, anomalia remediations, shinka
20//! migrations etc. reach for the same primitive instead of hand-
21//! rolling another `match` ladder.
22//!
23//! ## Surface
24//!
25//! ```ignore
26//! use gen_platform::{Dispatcher, TypedDispatcher};
27//!
28//! #[derive(serde::Serialize, serde::Deserialize, gen_platform::TypedDispatcher)]
29//! #[serde(tag = "kind", rename_all = "kebab-case")]
30//! enum Migration {
31//! AddColumn { table: String, column: String },
32//! DropIndex { name: String },
33//! }
34//!
35//! let dispatcher = Dispatcher::<Migration, MyCtx, MyOverride>::new()
36//! .helper("add-column", |variant, ctx| { /* ... */ Default::default() })
37//! .helper("drop-index", |variant, ctx| { /* ... */ Default::default() })
38//! .into_sealed() // enforces variant coverage
39//! .expect("every variant has a helper");
40//!
41//! let result = dispatcher.apply(&[migration_a, migration_b], &mut ctx);
42//! ```
43//!
44//! ## Re-exports
45//!
46//! - `gen_types::TypedDispatcher` — the reflection trait.
47//! - `gen_types::DispatcherVariant` — variant envelope shape.
48//! - `gen_macros::TypedDispatcher` — `#[derive]` macro.
49//!
50//! ## New primitives (this crate)
51//!
52//! - `Dispatcher<V, C, O>` — runtime applicator. Holds typed
53//! helpers per variant kind. `into_sealed()` proves coverage at
54//! construction time (every reflected kind has a registered
55//! helper) — silent unknown variants become impossible.
56//! - `SealedDispatcher<V, C, O>` — the post-seal handle; `apply`
57//! cannot fail on coverage anymore (proven at seal time).
58//! - `DispatcherError` — typed error for build-time issues
59//! (missing coverage, duplicate helpers).
60//! - `MergeStrategy` — how to fold per-variant overrides.
61
62#![allow(clippy::module_name_repetitions)]
63
64pub mod catalog;
65pub mod composed;
66pub mod dispatcher;
67pub mod emit;
68pub mod merge;
69
70pub use catalog::{by_label as catalog_by_label, registered as catalog_registered, DispatcherEntry};
71pub use composed::{ComposedDispatcher, ComposedSource};
72pub use dispatcher::{Dispatcher, DispatcherError, SealedDispatcher};
73pub use emit::to_helpers_skeleton;
74pub use merge::MergeStrategy;
75
76// Re-exports — single canonical Rust handle.
77pub use gen_macros::{BackendError, Discriminant, FromStrKind, IsVariant, OutcomeLattice, TypedDispatcher};
78pub use gen_types::{DispatcherVariant, TypedDispatcher as TypedDispatcherTrait};