rlua-searcher/src/searcher.rs
2021-02-04 12:16:07 +11:00

62 lines
2.2 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

use rlua::{Context, MetaMethod, RegistryKey, Table, UserData, UserDataMethods, Value};
use std::collections::HashMap;
use crate::types::Result;
/// Stores Lua modules indexed by module name, and provides an
/// `rlua::MetaMethod` to enable `require`ing the stored modules by name
/// in an `rlua::Context`.
struct Searcher {
/// A `HashMap` of Lua modules in `String` representation, indexed
/// by module name.
modules: HashMap<String, String>,
/// An `rlua::RegistryKey` whose value is the Lua environment within
/// which the user made the request to instantiate a `Searcher` for
/// `modules`.
globals: RegistryKey,
}
impl Searcher {
fn new(modules: HashMap<String, String>, globals: RegistryKey) -> Self {
Self { modules, globals }
}
}
impl UserData for Searcher {
fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(MetaMethod::Call, |lua_ctx, this, name: String| {
match this.modules.get(&name) {
Some(content) => Ok(Value::Function(
lua_ctx
.load(content)
.set_name(&name)?
.set_environment(lua_ctx.registry_value::<Table>(&this.globals)?)?
.into_function()?,
)),
None => Ok(Value::Nil),
}
});
}
}
/// Extend `rlua::Context` to support `require`ing Lua modules by name.
pub trait AddSearcher<'a> {
/// Add a `HashMap` of Lua modules indexed by module name to Luas
/// `package.searchers` table in an `rlua::Context`, with lookup
/// functionality provided by the `rlua_searcher::Searcher` struct.
fn add_searcher(&self, modules: HashMap<String, String>) -> Result<()>;
}
impl<'a> AddSearcher<'a> for Context<'a> {
fn add_searcher(&self, modules: HashMap<String, String>) -> Result<()> {
let globals = self.globals();
let searchers: Table = globals.get::<_, Table>("package")?.get("searchers")?;
let registry_key = self.create_registry_value(globals)?;
let searcher = Searcher::new(modules, registry_key);
searchers
.set(searchers.len()? + 1, searcher)
.map_err(|e| e.into())
}
}