1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
//! `Prebindgen` — what a generator still hands the emitter.
//!
//! One method per `#[prebindgen]` item kind (`on_function`, `on_struct`,
//! `on_enum`, `on_const`) returning the wrapper Rust tokens to emit, plus the
//! items they depend on (`prerequisites`), a cross-cutting rewrite
//! (`post_process_item`) and two invariant checks.
//!
//! **Conversion is not here.** A generator builds those itself, against the
//! demand `RegistryBuilder::crossings` hands it, and gives them back through
//! `RegistryBuilder::convert_with` — so there is no `on_input_type`, no deferral, and no
//! fixed-point loop retrying until it converges.
//!
//! [`ConverterImpl::function`] is the **complete** Rust function for a
//! converter — signature, body, attributes, lifetimes. The generator owns 100%
//! of the shape. Callers read the name from `function.sig.ident` and the wire
//! form from `destination`.
use TokenStream;
use crate::;
/// A shared predicate over an item name, as used by
/// `Prebindgen`'s ignore hooks (bulk ignores keyed on a naming
/// family rather than an exact ident).
pub type NamePredicate = Arc;
/// One link in a converter's [stage chain](`ConverterImpl::pre_stages`) —
/// a value-inspecting step that sits between the rust value the
/// `#[prebindgen]` fn yields/receives and the wire-facing
/// [`ConverterImpl::function`].
///
/// Each stage is a fallible `In → Result<Out, Err>` function. The core
/// pipeline only ever emits and de-duplicates [`Self::function`]; how a
/// stage's `Err` arm is surfaced to the foreign side — throw an exception,
/// return an error code, set `errno`, … — is entirely up to the
/// destination-language adapter and is described by [`Self::metadata`].
/// Result of resolving one converter — the wire (destination) type the rest
/// of the registry sees, plus the complete generated function.
///
/// Invariant: `function.sig.ident` MUST be a deterministic function of the
/// `(rust_type, destination)` pair so that callers of this converter — both
/// other generated converters from the same adapter and any hand-written code
/// that knows the convention — can compute or look up the name.
/// The single extension point of the pipeline: implement this trait once per
/// **destination language** (C/cbindgen, JNI/Kotlin, Swift, Python, …) to teach
/// the language-agnostic [`Registry`] how that language represents Rust types
/// on the wire and what wrapper code to emit.
///
/// The trait has no language-specific concepts of its own, and — since the
/// registry stopped asking it questions — one job left: **per-item emission**.
/// The file emitter calls `on_function` / `on_struct` / `on_enum` / `on_const`
/// to produce the per-item wrapper code, plus `prerequisites` and
/// `post_process_item` around them and the two `validate` hooks for
/// adapter invariants.
///
/// What used to be here and is not any more: which items to build, how
/// composites decompose, and the wire form of each type. A generator states the
/// first two into the builder (`RegistryBuilder::export`,
/// `RegistryBuilder::decompose`)
/// and answers the third by filling `RegistryBuilder::crossings` — so nothing in
/// core calls back to ask. Moving emission out too is what would delete this
/// trait entirely (prebindgen#251 phase E).
///
/// Anything language-specific the rest of the pipeline must carry — a JNI
/// adapter's Kotlin class names and exception info, a C adapter's header
/// names, etc. — rides in [`Self::Metadata`], an opaque type the adapter
/// chooses. It is set in each `ConverterImpl::metadata`, propagated by the
/// resolver into `TypeEntry::metadata`, and read back by the adapter's own
/// emitter. Adapters that need no extras leave it at the default `()`.
///
/// # The rule an adapter must obey
///
/// "Classify off [`kind`](crate::flat::TypeRef::kind), spell off the syntax"
/// tells an adapter where to get each fact. It is silent on the question
/// adapters actually face — what the **destination language** ends up seeing.
/// That one has its own answer:
///
/// > **Same `kind` ⇒ same destination-language type.** The *wire* is the
/// > generator's to choose, and may differ per spelling.
///
/// The weaker-sounding half is the important one. It is tempting to write "same
/// `kind` ⇒ same wire", and that is **false** — prebindgen's own adapters
/// violate it deliberately:
///
/// | Rust | `kind` | Kotlin type | wire |
/// |---|---|---|---|
/// | `&[Payload]` | `Ref(Slice)` | `List<Payload>` | `Long` — a handle to a Rust-side `Vec` |
/// | `Vec<Box<Payload>>` | `Vec(Boxed)` | `List<Payload>` | `JObject` — a Java `List<Payload>` |
///
/// Two wires, one surface. Choosing a wire is exactly the generator's job, and
/// the destination-language wrapper absorbs the difference; a caller cannot
/// tell. What a caller *can* tell — and what
/// [`unwrapped`](crate::flat::TypeRef::unwrapped) exists to prevent — is the
/// **type** changing because the source spelled a `Box`.
///
/// The rule scopes to **converted** positions: those where a converter stands
/// between the Rust value and the destination and is therefore free to bridge.
/// It cannot apply to a **layout mirror**, where the destination type is
/// reinterpreted from the source struct's bytes and is a *layout* fact rather
/// than a surface choice — there `Box<T>` (a pointer) genuinely is a different
/// destination type from `T` (inline), the spelling is load-bearing by
/// construction, and no erasure can apply. The C adapter's `repr_c_struct` is
/// the one such position in-tree, and its own documentation carries that half.
///
/// Reusing a mirror's spelling test in a converted position is how the rule
/// gets broken (prebindgen#230, #292).