prebindgen_registry/registry/cell.rs
1//! What a crossing IS: the type it names, the conversion for it, and which way
2//! it goes.
3
4use super::*;
5
6/// One type-table cell: what the key names, and the adapter's answer for it.
7pub(crate) struct TypeCell<M = ()> {
8 /// The frontend's reading of this type, reused whole — so its classification
9 /// and its origin are already here rather than re-derived per consumer.
10 ///
11 /// **Every** cell has one. There used to be a second variant for "a type only
12 /// the binding authored", on the assumption that a declared wire type or an
13 /// [`unfold`](crate::unfold) leaf had no reading to give. It did:
14 /// those are ordinary types in this language, they were simply absent from an
15 /// index of what the *source* wrote. `ensure_entry` takes the reading from the
16 /// grammar when the cell is born and stores it right here, so it is always
17 /// present, and a spelling the grammar genuinely refuses is a
18 /// [`ScanError::NotExpressible`] naming it rather than a cell that quietly means
19 /// less than its neighbours.
20 pub subject: Box<prebindgen_flat::flat::TypeRef>,
21 /// The binding asks for this cell **directly** — a declared fn's signature, a
22 /// declared type, an `unfold` leaf — as opposed to reaching it through some
23 /// converter's [`TypeEntry::subs`].
24 ///
25 /// A scan fact. Whether a converter is *needed* here is reachability from
26 /// these roots, which [`crate::resolve`] derives rather than
27 /// stores: the scan deliberately over-approximates the table (every nested
28 /// position, every struct in both directions), so the roots are what say
29 /// which of it has to work.
30 pub root: bool,
31 /// The adapter's converter, once resolved.
32 pub entry: Option<TypeEntry<M>>,
33}
34
35/// Per-cell registry entry.
36#[derive(Clone)]
37pub struct TypeEntry<M = ()> {
38 /// Wire/destination type — the form the value takes on the wire as
39 /// chosen by the adapter (e.g. an `i64` handle for a JNI adapter, or
40 /// a `*const T` raw pointer for a C adapter). Other converters that
41 /// ask "what's the wire form of this rust type?" read this.
42 pub destination: syn::Type,
43 /// Complete generated function for the **wire-facing** stage of the
44 /// converter (signature, body, attributes, lifetimes). The adapter
45 /// owns the shape. Callers compute this stage's name via
46 /// `function.sig.ident`.
47 pub function: syn::ItemFn,
48 /// **Rust-side** stages that compose with [`Self::function`] to form
49 /// the full chain — copied verbatim from the resolving
50 /// [`crate::prebindgen::ConverterImpl::pre_stages`]. See
51 /// that field's docs for the chain-order semantics.
52 pub pre_stages: Vec<Stage<M>>,
53 /// Inner types whose function delegates to their converters. Empty for
54 /// terminal converters; populated by wrapper converters. Used by the
55 /// post-resolution propagation pass.
56 pub subs: Vec<TypeKey>,
57 /// Wire bit-patterns this converter never produces / always rejects.
58 /// Wrappers (`Option<_>`, sum-typed enums) carve from this set for
59 /// their own discriminants. See [`Niches`] for the cascade model.
60 pub niches: Niches,
61 /// Adapter-specific extras carried in by the
62 /// [`crate::prebindgen::ConverterImpl`] that filled this
63 /// slot. Emitter code reads this directly — the registry is the
64 /// single source of truth for cross-language facts (C header names,
65 /// JVM class names, etc.). Defaults to `()` for adapters that don't
66 /// need any.
67 pub metadata: M,
68}
69
70impl<M> TypeEntry<M> {
71 /// The resolved form of what a generator built.
72 ///
73 /// The only difference is `subs`: a generator names its inners as types,
74 /// and the table keys them.
75 pub fn from_converter(c: crate::ConverterImpl<M>) -> Self {
76 Self {
77 destination: c.destination,
78 function: c.function,
79 pre_stages: c.pre_stages,
80 subs: c.subs.clone(),
81 niches: c.niches,
82 metadata: c.metadata,
83 }
84 }
85
86 /// Identifier of the wire-facing converter function.
87 pub fn converter_ident(&self) -> &syn::Ident {
88 &self.function.sig.ident
89 }
90
91 /// Wire/destination type carried by this converter on success.
92 pub fn wire_type(&self) -> &syn::Type {
93 &self.destination
94 }
95
96 /// Rust-side stages in input execution order, after the wire-facing
97 /// converter has decoded the wire value.
98 pub fn input_stage_order(&self) -> impl Iterator<Item = (usize, &Stage<M>)> {
99 self.pre_stages.iter().enumerate().rev()
100 }
101
102 /// Rust-side stages in output execution order, before the wire-facing
103 /// converter encodes the final wire value.
104 pub fn output_stage_order(&self) -> impl Iterator<Item = (usize, &Stage<M>)> {
105 self.pre_stages.iter().enumerate()
106 }
107
108 /// Immediate converter dependencies recorded by the adapter when this entry
109 /// resolved.
110 pub fn dependency_keys(&self) -> &[TypeKey] {
111 &self.subs
112 }
113}
114
115/// Direction of a converter pair.
116#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
117pub enum Direction {
118 /// Wire → Rust.
119 Input,
120 /// Rust → Wire.
121 Output,
122}
123
124impl Direction {
125 pub fn flip(self) -> Self {
126 match self {
127 Direction::Input => Direction::Output,
128 Direction::Output => Direction::Input,
129 }
130 }
131}