Skip to main content

prebindgen_registry/registry/
model.rs

1//! Questions about the model, answered through the registry that projects it.
2
3use std::collections::HashMap;
4
5use super::{
6    view::{default_module_of, origin_module_of},
7    *,
8};
9
10impl<M> Registry<M> {
11    /// The parameter-side fold for each `(function, parameter)` position.
12    ///
13    /// Inherent rather than on [`Conversions`]: a fold is read when a wrapper's
14    /// parameters are emitted, never while a conversion is being built, so no
15    /// generic caller needs it.
16    pub fn expansion_plans(&self) -> &HashMap<(syn::Ident, syn::Ident), crate::expand::FoldPlan> {
17        &self.expansion_plans
18    }
19
20    /// What the binding declared — read by the emitter's gate.
21    pub(crate) fn declared(&self) -> &Declared {
22        &self.declared
23    }
24
25    /// The parsed model this registry projects.
26    pub fn flat(&self) -> &prebindgen_flat::flat::Flat {
27        &self.flat
28    }
29
30    /// Every **named** item the model holds — functions, structs, either enum
31    /// shape, consts — regardless of whether the stream carried an origin stamp.
32    ///
33    /// Lives here so an adapter that needs "anything the source crate defines"
34    /// does not enumerate element kinds itself: a new kind is taught here once
35    /// instead of drifting in each adapter. An **alias is deliberately absent**
36    /// — see the arm below — and callers are expected to pair this with
37    /// `origin_module(..).unwrap_or_else(default_module)`.
38    pub fn named_item_idents(&self) -> impl Iterator<Item = &syn::Ident> {
39        use prebindgen_flat::flat::{Element, Type};
40        self.flat.elements().filter_map(|e| match e {
41            // An `Extern` names a type without declaring a body, and is
42            // deliberately absent: its caller decides which names to qualify in
43            // generated Rust, and qualifying an alias would move that output.
44            Element::Type(Type::Extern(_)) => None,
45            Element::Function(_) | Element::Type(_) | Element::Constant(_) => e.name(),
46            Element::Guard(_) | Element::Unsupported(_) => None,
47        })
48    }
49
50    /// Whether the source declares a type under this name — **including an
51    /// alias**.
52    ///
53    /// An alias counts because `#[prebindgen] pub type Handle = ..` *is* a
54    /// declaration of that name: it can be declared bare by an adapter (landing
55    /// in the no-indexed-body branch below, which is what
56    /// `ptr_class(ZKeyExpr<'static>)` relies on), so a diagnostic that says
57    /// "no such captured item" would be false.
58    pub(super) fn declares_type(&self, ident: &syn::Ident) -> bool {
59        self.flat.declared_type(ident).is_some()
60    }
61
62    /// The origin crate's **module path** for an item, read off the element's
63    /// own [`SourceLocation`] stamp, or `None` when unknown — callers then fall
64    /// back to [`Self::default_module`].
65    pub fn origin_module(&self, ident: &syn::Ident) -> Option<syn::Path> {
66        // Off the element's own location, which covers both populations: a
67        // captured item stamped at capture time, and a binding-local fn stamped
68        // by `add_local_function`.
69        origin_module_of(&self.flat, ident)
70    }
71
72    /// The default module for references with no recorded origin: the
73    /// first-seen item origin. `None` for an origin-less item-level
74    /// registry (adapters then fall back to `crate`). To change a module
75    /// name, override it at the source — a stream's origin stamps
76    /// (`Source::builder(dir).crate_name("myflat")`) — never here: a
77    /// registry-level override could only fix ONE module, which is
78    /// incomplete with chained multi-source streams.
79    pub fn default_module(&self) -> Option<syn::Path> {
80        default_module_of(&self.flat)
81    }
82
83    /// Module paths of every ingested source, ingestion order — e.g. for a
84    /// glob import that must see all sources' items.
85    pub fn all_source_modules(&self) -> Vec<syn::Path> {
86        self.flat
87            .source_modules()
88            .iter()
89            .filter_map(|m| syn::parse_str(m).ok())
90            .collect()
91    }
92}