Skip to main content

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}