opy_rs/compiler/
integration.rs1use super::*;
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub struct LinkReport {
8 pub catalog_ids_checked: usize,
9 pub domains_checked: usize,
10}
11
12pub(crate) fn cross_check_manifest(
16 manifest: &Manifest,
17 catalog: &Catalog,
18) -> Result<LinkReport, IntegrationError> {
19 #[cfg(test)]
20 crate::resource_metrics::record_contract_check();
21 let mut catalog_ids_checked = 0;
22 let mut domains_checked = 0;
23
24 for function in &manifest.functions {
25 if let Some(catalog_id) = &function.catalog_id {
26 let kind = match function.kind {
27 FunctionKind::Action | FunctionKind::MemberAction => Kind::Action,
28 FunctionKind::Value | FunctionKind::MemberValue => Kind::Value,
29 };
30 catalog_ids_checked += 1;
31 if catalog.entry(kind, catalog_id).is_none() {
32 return Err(IntegrationError::new(
33 "catalog-link-missing",
34 format!(
35 "manifest function '{}' links to missing {:?} catalog id '{}'",
36 function.id, kind, catalog_id
37 ),
38 None,
39 ));
40 }
41 }
42
43 for parameter in &function.params {
44 let Some(domain) = ¶meter.domain else {
45 continue;
46 };
47 if crate::lower::policy::is_contextual_domain(domain) {
48 continue;
49 }
50 domains_checked += 1;
51 if catalog.enum_domain(domain).is_none() {
52 return Err(IntegrationError::new(
53 "domain-link-missing",
54 format!(
55 "manifest function '{}' parameter '{}' links to missing enum domain '{}',",
56 function.id, parameter.name, domain
57 ),
58 None,
59 ));
60 }
61 }
62
63 if let Some(contextual) = crate::lower::policy::contextual_domain(&function.id) {
64 for option in contextual.options {
65 domains_checked += 1;
66 if catalog.enum_domain(option.domain).is_none() {
67 return Err(IntegrationError::new(
68 "domain-link-missing",
69 format!(
70 "manifest function '{}' contextual option links to missing enum domain '{}'",
71 function.id, option.domain
72 ),
73 None,
74 ));
75 }
76 }
77 }
78 }
79
80 Ok(LinkReport {
81 catalog_ids_checked,
82 domains_checked,
83 })
84}
85
86pub(crate) fn load_compiler_contract()
87-> Result<(Catalog, &'static Manifest, LinkReport), IntegrationError> {
88 let catalog = Catalog::builtin()
89 .map_err(|error| IntegrationError::new("catalog-load", error.to_string(), None))?;
90 let manifest = Manifest::builtin()
91 .map_err(|error| IntegrationError::new("manifest-load", error.to_string(), None))?;
92 let links = cross_check_manifest(manifest, &catalog)?;
93 Ok((catalog, manifest, links))
94}