prebindgen_registry/expand/plan.rs
1//! Resolved constructor-expansion plans.
2
3/// Outer shape wrapping the core construct. The value-side analog of how the
4/// `Option<_>` / `Vec<_>` wrapper converters compose at the wire.
5///
6/// The unified [`Shape`](prebindgen_flat::shape::Shape) layer stack: `Base`
7/// builds the target directly from the decoded leaves (a single constructor of
8/// any arity or a combined-selector dispatch); `Optional((), inner)` lifts that
9/// over `Option<T>`/`Option<&T>` (`Some` ⇒ run `inner` on the unwrapped value
10/// and re-wrap, `None` ⇒ `None`; inner is always `Base` today);
11/// `Iterable(inner)` maps `inner` over each element of a `Vec<T>` (emit-ready
12/// but not yet produced by `apply`). The `()` payload is unused here — only the
13/// JNI adapter's `Shape<NullableKind>` carries per-layer data.
14pub use prebindgen_flat::shape::Shape as FoldShape;
15
16/// A resolved expansion for one `(function, parameter)`.
17#[derive(Clone)]
18pub struct FoldPlan {
19 /// Owned type the core construct produces — what the underlying call needs
20 /// (before any [`Self::shape`] wrapping). A **reading**: `target.spell()`
21 /// for generated Rust, `target.key()` for a lookup.
22 pub target: prebindgen_flat::flat::TypeRef,
23 /// True when the original parameter was `&T` / `Option<&T>`: the call
24 /// receives `&folded` (or `folded.as_ref()` when also optional). A
25 /// call-site concern (the resolver's `&_` handler shares the inner
26 /// converter the same way), not part of the fold.
27 pub by_ref: bool,
28 /// Outer shape over the core construct (`Construct` for a plain `T`/`&T`
29 /// param; `Optional(Construct)` for `Option<T>`/`Option<&T>`).
30 pub shape: FoldShape,
31 /// Flattened wire leaves, in foreign-signature order.
32 pub leaves: Vec<FoldLeaf>,
33 /// Index into [`Self::leaves`] of the selector leaf; `None` for a single
34 /// constructor (the sole variant is applied unconditionally). Under an
35 /// [`Optional`](FoldShape::Optional) shape the selector also encodes
36 /// **absence**: `-1` = `None`, `0..n-1` = the taken arm.
37 pub selector: Option<usize>,
38 /// Index into [`Self::leaves`] of the explicit presence-flag (`bool`) leaf
39 /// for a **multi-argument** `Optional` shape (`Option<T>` built from a
40 /// constructor taking ≥2 args): the flag decides `Some`/`None`, the arg
41 /// leaves are plain (non-`Option`). `None` for a non-optional fold or the
42 /// legacy single-arg `Optional` (where presence rides the sole leaf's own
43 /// `Option`-ness). A separate flag avoids boxing a nullable primitive arg
44 /// (e.g. `Option<i32>` → `Integer?`) on the wire.
45 pub present: Option<usize>,
46 /// Dispatch arms — one for a single constructor, selector order for a
47 /// combined one.
48 pub variants: Vec<FoldVariant>,
49}
50
51impl FoldPlan {
52 /// True when the fold produces an `Option<_>` (outermost shape layer is
53 /// `Optional`) — drives the by-ref call-site form (`folded.as_ref()`).
54 pub fn produces_option(&self) -> bool {
55 matches!(self.shape, FoldShape::Optional((), _))
56 }
57}
58
59/// One flattened wire leaf of an expanded parameter.
60#[derive(Clone)]
61pub struct FoldLeaf {
62 /// Foreign-side parameter name.
63 pub name: syn::Ident,
64 /// The **reading** of the type whose resolved input converter decodes this
65 /// leaf. For a single constructor these are the raw constructor parameter
66 /// types; for a combined one the selector (`i32`) and `Option`-wrapped
67 /// variant inputs. Spell it with `ty.spell()`.
68 ///
69 /// A reading rather than a spelling for the reason `UnfoldLeaf::out_ty`
70 /// gives: a consumer asking what this leaf's type MEANS had to hand the
71 /// spelling back to the registry (#275). The leaves no source wrote — the
72 /// presence flag, the selector — are built by
73 /// [`TypeRef::scalar`](prebindgen_flat::flat::TypeRef::scalar), which
74 /// pairs the kind with its own spelling and is placeless by construction.
75 pub ty: prebindgen_flat::flat::TypeRef,
76}
77
78/// One dispatch arm of a [`FoldPlan`].
79#[derive(Clone)]
80pub struct FoldVariant {
81 /// `None` => identity (pass the decoded target value through). `Some` =>
82 /// call this constructor function.
83 pub ctor: Option<syn::Ident>,
84 /// Whether the constructor returns `Result` (its `Err` is routed through
85 /// the adapter's error channel). Always `false` for identity.
86 pub fallible: bool,
87 /// `true` for a borrowed identity arm (`&T` parameter): the input leaf is
88 /// `Option<&T>` and the fold clones it (`T: Clone`) so the caller's handle
89 /// is preserved rather than consumed. `false` otherwise.
90 pub clone: bool,
91 /// This variant's constructor inputs, in parameter order. Each is either a
92 /// flat wire leaf or a recursively-built sub-value (a parameter that is
93 /// itself a type with a default constructor — recursive input).
94 pub inputs: Vec<FoldArg>,
95}
96
97/// One constructor-parameter input of a [`FoldVariant`].
98#[derive(Clone)]
99pub enum FoldArg {
100 /// Decode the flat wire leaf at this index into [`FoldPlan::leaves`].
101 ///
102 /// The `bool` is the **passthrough** marker for selector-dispatched arms:
103 /// `false` = the leaf is `Option`-wrapped by selector presence and is
104 /// unwrapped before the constructor call (a missing input is an error);
105 /// `true` = the constructor argument is itself an `Option<…>`, so the leaf
106 /// keeps the argument's own type and passes through unwrapped (`None` is a
107 /// legitimate value for the taken arm — arm-taken-ness is decided by the
108 /// selector alone). Always `false` outside dispatched arms.
109 Leaf(usize, bool),
110 /// Build this parameter by recursively folding its own default
111 /// constructor (the parameter's type is itself a ptr_class with a default
112 /// input). Its leaves live in the shared flat [`FoldPlan::leaves`].
113 Build(Box<FoldBuild>),
114}
115
116/// A recursively-nested construction for one [`FoldArg::Build`] parameter — the
117/// same dispatch shape as a top-level [`FoldPlan`]'s core, minus the outer
118/// `Option`/`Vec` wrapping (a nested param is built by value).
119#[derive(Clone)]
120pub struct FoldBuild {
121 /// Owned type this nested build produces (the constructor parameter type).
122 pub target: prebindgen_flat::flat::TypeRef,
123 /// `true` when the consuming parameter is `&T` (the built value is borrowed
124 /// at the call site).
125 pub by_ref: bool,
126 /// Selector leaf index for a combined nested build; `None` for a single one.
127 pub selector: Option<usize>,
128 /// Dispatch arms (recursive).
129 pub variants: Vec<FoldVariant>,
130}