jigs_core/meta.rs
1//! Compile-time metadata for every `#[jig]` function in the binary.
2//!
3//! The `#[jig]` macro emits one [`JigMeta`] per annotated function and
4//! registers it via the `inventory` crate. Consumers iterate them at runtime
5//! through [`all`].
6
7/// How a chain entry was reached from the surrounding jig.
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum ChainKind {
10 /// Reached via `.then(...)` — sequential composition. Output of the
11 /// previous step flows into this one.
12 Then,
13 /// Reached via `fork!(...)` — alternative arm. Sibling arms do not
14 /// flow into each other; exactly one arm runs per request.
15 Fork,
16}
17
18/// One entry in a jig's chain: the called jig's name plus how it was
19/// composed with the surrounding pipeline.
20#[derive(Debug, Clone, Copy)]
21pub struct ChainStep {
22 /// Name of the jig referenced at this step.
23 pub name: &'static str,
24 /// Compositional relationship to the surrounding jig.
25 pub kind: ChainKind,
26}
27
28/// Static description of one jig.
29#[derive(Debug, Clone, Copy)]
30pub struct JigMeta {
31 /// Function name as written in source.
32 pub name: &'static str,
33 /// Source file path (as seen by the compiler at expansion time).
34 pub file: &'static str,
35 /// 1-based line of the function declaration.
36 pub line: u32,
37 /// Outer return-type identifier: `"Request"`, `"Response"`, `"Branch"`,
38 /// `"Pending"`, or `"Other"`.
39 pub kind: &'static str,
40 /// Outer first-argument type identifier: `"Request"`, `"Response"`, or
41 /// `"Other"`. Combined with [`Self::kind`] this places a jig in one of three
42 /// semantic buckets: request-side (Request → Request), switching
43 /// (Request → Response/Branch) or response-side (Response → Response).
44 pub input: &'static str,
45 /// Exact payload type coming in (e.g. `"Raw"`, `"u32"`, `"Response<HttpResponse>"`).
46 pub input_type: &'static str,
47 /// Exact payload type going out (e.g. `"HttpResponse"`, `"String"`, `"Branch<Ctx,OrderResult>"`).
48 pub output_type: &'static str,
49 /// `true` if the underlying function is `async fn`.
50 pub is_async: bool,
51 /// Rust module path of the function (e.g. `crate::features::orders`).
52 pub module: &'static str,
53 /// Jigs this function references, in source order, tagged with how
54 /// they were composed (`.then(...)` vs `fork!(...)` arm).
55 pub chain: &'static [ChainStep],
56}
57
58impl JigMeta {
59 /// Iterator over chain step names, ignoring kind. Convenience for
60 /// callers that only care about the referenced jig names.
61 pub fn chain_names(&self) -> impl Iterator<Item = &'static str> + '_ {
62 self.chain.iter().map(|s| s.name)
63 }
64}
65
66inventory::collect!(JigMeta);
67
68/// Iterator over every jig registered in the current binary.
69pub fn all() -> impl Iterator<Item = &'static JigMeta> {
70 inventory::iter::<JigMeta>()
71}
72
73/// Look up a jig by name. `O(N)` over the registry.
74pub fn find(name: &str) -> Option<&'static JigMeta> {
75 all().find(|m| m.name == name)
76}