presolve_compiler/
semantic_package_runtime.rs1use std::collections::BTreeMap;
4
5use crate::SemanticPackageContract;
6
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
8pub struct SemanticPackageRuntimeModuleKey {
9 pub package: String,
10 pub version: String,
11 pub integrity: String,
12 pub runtime_module: String,
13}
14
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub enum SemanticPackageRuntimeModuleError {
17 EmptyLocation,
18 DuplicateRuntimeModule,
19 ContractMismatch,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, Default)]
25pub struct SemanticPackageRuntimeModuleTable {
26 modules: BTreeMap<SemanticPackageRuntimeModuleKey, String>,
27}
28
29impl SemanticPackageRuntimeModuleTable {
30 pub fn insert(
31 &mut self,
32 key: SemanticPackageRuntimeModuleKey,
33 location: String,
34 ) -> Result<(), SemanticPackageRuntimeModuleError> {
35 if location.is_empty() {
36 return Err(SemanticPackageRuntimeModuleError::EmptyLocation);
37 }
38 if self.modules.contains_key(&key) {
39 return Err(SemanticPackageRuntimeModuleError::DuplicateRuntimeModule);
40 }
41 self.modules.insert(key, location);
42 Ok(())
43 }
44
45 #[must_use]
46 pub fn resolve(&self, key: &SemanticPackageRuntimeModuleKey) -> Option<&str> {
47 self.modules.get(key).map(String::as_str)
48 }
49
50 #[must_use]
51 pub fn contains(&self, key: &SemanticPackageRuntimeModuleKey) -> bool {
52 self.modules.contains_key(key)
53 }
54
55 pub fn resolve_contract_module(
56 &self,
57 contract: &SemanticPackageContract,
58 runtime_module: &str,
59 ) -> Result<&str, SemanticPackageRuntimeModuleError> {
60 let key = SemanticPackageRuntimeModuleKey {
61 package: contract.package.clone(),
62 version: contract.version.clone(),
63 integrity: contract.integrity.clone(),
64 runtime_module: runtime_module.to_string(),
65 };
66 self.resolve(&key)
67 .ok_or(SemanticPackageRuntimeModuleError::ContractMismatch)
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use crate::{
74 parse_semantic_package_contract, SemanticPackageRuntimeModuleError,
75 SemanticPackageRuntimeModuleKey, SemanticPackageRuntimeModuleTable,
76 };
77
78 #[test]
79 fn resolves_only_the_exact_integrity_checked_runtime_module_coordinate() {
80 let contract = parse_semantic_package_contract(
81 r#"{"schema_version":1,"package":"profile-service","version":"1.2.3","integrity":"sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa","exports":{"loadProfile":{"kind":"resource","type_signature":"() -> Resource<string, string>","runtime_module":"dist/load-profile.js","resume_policy":"snapshot","resource_endpoint":{"execution_boundary":"shared","cancellation":"abort","resume":"snapshot"}}}}"#,
82 )
83 .unwrap();
84 let mut modules = SemanticPackageRuntimeModuleTable::default();
85 modules
86 .insert(
87 SemanticPackageRuntimeModuleKey {
88 package: "profile-service".into(),
89 version: "1.2.3".into(),
90 integrity:
91 "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
92 .into(),
93 runtime_module: "dist/load-profile.js".into(),
94 },
95 "./vendor/profile-service.js".into(),
96 )
97 .unwrap();
98 assert_eq!(
99 modules
100 .resolve_contract_module(&contract, "dist/load-profile.js")
101 .unwrap(),
102 "./vendor/profile-service.js"
103 );
104 assert_eq!(
105 modules.resolve_contract_module(&contract, "other.js"),
106 Err(SemanticPackageRuntimeModuleError::ContractMismatch)
107 );
108 }
109}