Skip to main content

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}