1use crate::{
2 LibId,
3 env::Cx,
4 error::{Error, Result},
5 library::{Lib, LibTarget, Version},
6};
7
8use super::claims::publish_loaded_lib_claims;
9use super::loaders::dependency_satisfied;
10
11impl Cx {
12 pub fn load_lib(&mut self, lib: &dyn Lib) -> Result<LibId> {
16 let manifest = lib.manifest();
17 for capability in &manifest.capabilities {
18 self.require(capability)?;
19 }
20 for dependency in &manifest.requires {
21 if let Some(loaded_manifest) = self.registry.manifest_by_symbol(&dependency.id)
22 && !dependency_satisfied(loaded_manifest, dependency)
23 {
24 return Err(Error::DependencyVersionMismatch {
25 lib: manifest.id.clone(),
26 dependency: dependency.id.clone(),
27 required: dependency
28 .minimum_version
29 .clone()
30 .unwrap_or_else(|| Version(String::from("0"))),
31 loaded: loaded_manifest.version.clone(),
32 });
33 }
34 }
35 let trusted = matches!(manifest.target, LibTarget::HostRegistered);
36 let mut txn = self.registry.begin_load(manifest, trusted);
37 {
38 let mut load_cx = self.load_cx();
39 let mut linker = txn.linker();
40 lib.load(&mut load_cx, &mut linker)?;
41 }
42 let lib_id = self.registry.commit_load(txn)?;
43 let loaded = self
44 .registry
45 .libs()
46 .iter()
47 .find(|loaded| loaded.id == lib_id)
48 .cloned();
49 if let Some(loaded) = loaded {
50 let claim_ids = publish_loaded_lib_claims(self, &loaded)?;
51 self.record_load_claims(lib_id, claim_ids);
52 }
53 Ok(lib_id)
54 }
55
56 pub fn load_libs(&mut self, libs: &[&dyn Lib]) -> Result<Vec<LibId>> {
59 let manifests = libs.iter().map(|lib| lib.manifest()).collect::<Vec<_>>();
60 let ordered = self.registry.dependency_order(&manifests)?;
61 let mut ids = Vec::with_capacity(ordered.len());
62
63 for manifest in ordered {
64 let lib = libs
65 .iter()
66 .find(|candidate| candidate.manifest().id == manifest.id)
67 .ok_or_else(|| {
68 Error::Lib(format!("missing lib implementation for {}", manifest.id))
69 })?;
70 ids.push(self.load_lib(*lib)?);
71 }
72
73 Ok(ids)
74 }
75
76 pub fn unload_lib(&mut self, lib_id: LibId) -> Result<Vec<LibId>> {
81 let unloaded = self.registry.unload(lib_id)?;
82 self.remove_load_claims(&unloaded);
83 Ok(unloaded)
84 }
85
86 pub fn unload_lib_cascade(&mut self, lib_id: LibId) -> Result<Vec<LibId>> {
89 let unloaded = self.registry.unload_cascade(lib_id)?;
90 self.remove_load_claims(&unloaded);
91 Ok(unloaded)
92 }
93}