use crate::{
LibId,
env::Cx,
error::{Error, Result},
library::{Lib, LibTarget, Version},
};
use super::claims::publish_loaded_lib_claims;
use super::loaders::dependency_satisfied;
impl Cx {
pub fn load_lib(&mut self, lib: &dyn Lib) -> Result<LibId> {
let manifest = lib.manifest();
for capability in &manifest.capabilities {
self.require(capability)?;
}
for dependency in &manifest.requires {
if let Some(loaded_manifest) = self.registry.manifest_by_symbol(&dependency.id)
&& !dependency_satisfied(loaded_manifest, dependency)
{
return Err(Error::DependencyVersionMismatch {
lib: manifest.id.clone(),
dependency: dependency.id.clone(),
required: dependency
.minimum_version
.clone()
.unwrap_or_else(|| Version(String::from("0"))),
loaded: loaded_manifest.version.clone(),
});
}
}
let trusted = matches!(manifest.target, LibTarget::HostRegistered);
let mut txn = self.registry.begin_load(manifest, trusted);
{
let mut load_cx = self.load_cx();
let mut linker = txn.linker();
lib.load(&mut load_cx, &mut linker)?;
}
let lib_id = self.registry.commit_load(txn)?;
let loaded = self
.registry
.libs()
.iter()
.find(|loaded| loaded.id == lib_id)
.cloned();
if let Some(loaded) = loaded {
let claim_ids = publish_loaded_lib_claims(self, &loaded)?;
self.record_load_claims(lib_id, claim_ids);
}
Ok(lib_id)
}
pub fn load_libs(&mut self, libs: &[&dyn Lib]) -> Result<Vec<LibId>> {
let manifests = libs.iter().map(|lib| lib.manifest()).collect::<Vec<_>>();
let ordered = self.registry.dependency_order(&manifests)?;
let mut ids = Vec::with_capacity(ordered.len());
for manifest in ordered {
let lib = libs
.iter()
.find(|candidate| candidate.manifest().id == manifest.id)
.ok_or_else(|| {
Error::Lib(format!("missing lib implementation for {}", manifest.id))
})?;
ids.push(self.load_lib(*lib)?);
}
Ok(ids)
}
pub fn unload_lib(&mut self, lib_id: LibId) -> Result<Vec<LibId>> {
let unloaded = self.registry.unload(lib_id)?;
self.remove_load_claims(&unloaded);
Ok(unloaded)
}
pub fn unload_lib_cascade(&mut self, lib_id: LibId) -> Result<Vec<LibId>> {
let unloaded = self.registry.unload_cascade(lib_id)?;
self.remove_load_claims(&unloaded);
Ok(unloaded)
}
}