Skip to main content

jigs_core/
meta.rs

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