use std::path::{Path, PathBuf};
use mlua_pkg::{
resolvers::{FsResolver, PrefixResolver},
Registry, Resolver,
};
use crate::resolver_factory::make_resolver;
#[derive(Clone, Debug)]
pub struct VariantPkg {
pub name: String,
pub pkg_dir: PathBuf,
}
impl VariantPkg {
pub fn new(name: impl Into<String>, pkg_dir: impl Into<PathBuf>) -> Self {
Self {
name: name.into(),
pkg_dir: pkg_dir.into(),
}
}
}
struct VariantRootResolver {
name: String,
init_path: PathBuf,
}
impl Resolver for VariantRootResolver {
fn resolve(&self, lua: &mlua::Lua, req: &str) -> Option<mlua::Result<mlua::Value>> {
if req != self.name {
return None;
}
let content = match std::fs::read_to_string(&self.init_path) {
Ok(c) => c,
Err(e) => {
return Some(Err(mlua::Error::external(format!(
"variant pkg '{}': failed to read {:?}: {e}",
self.name, self.init_path
))));
}
};
Some(
lua.load(content)
.set_name(self.init_path.display().to_string())
.eval(),
)
}
}
fn make_submodule_resolver(pkg_dir: &Path) -> Option<FsResolver> {
make_resolver(pkg_dir)
}
pub(crate) fn register_variant_pkgs(reg: &mut Registry, variant_pkgs: &[VariantPkg]) {
for vp in variant_pkgs {
let init_path = vp.pkg_dir.join("init.lua");
reg.add(VariantRootResolver {
name: vp.name.clone(),
init_path,
});
match make_submodule_resolver(&vp.pkg_dir) {
Some(inner) => {
reg.add(PrefixResolver::new(vp.name.clone(), inner));
}
None => {
tracing::warn!(
"variant pkg '{}': sandbox init failed for {}, submodules disabled",
vp.name,
vp.pkg_dir.display()
);
}
}
}
}