make initial implementation
credit - https://github.com/AlphaModder/include-lua
This commit is contained in:
parent
187c5f55ea
commit
38c15af4dc
20
README.md
20
README.md
@ -11,20 +11,24 @@ and `require` the module.
|
||||
## Synopsis
|
||||
|
||||
```rust
|
||||
use rlua_searcher::AddSearcher;
|
||||
use rlua::Lua;
|
||||
use rlua_searcher::{AddSearcher, Result};
|
||||
use std::collections::HashMap;
|
||||
|
||||
fn main() {
|
||||
let lume = read_lume_to_string();
|
||||
let name = "lume";
|
||||
let map = HashMap::new<String, String>();
|
||||
let name = "lume".to_string();
|
||||
let mut map = HashMap::new();
|
||||
map.insert(name, lume);
|
||||
|
||||
let lua = Lua::new;
|
||||
let lua = Lua::new();
|
||||
|
||||
let hello = lua.context::<_, rlua::Result<_>>(|lua_ctx| {
|
||||
lua_ctx.add_searcher(map)?;
|
||||
Ok(lua_ctx.load(r#"require("lume")"#).eval()?)
|
||||
}).unwrap();
|
||||
let hello = lua
|
||||
.context::<_, Result<String>>(|lua_ctx| {
|
||||
lua_ctx.add_searcher(map)?;
|
||||
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
// prints "hello lume"
|
||||
println!("{}", hello);
|
||||
|
21
src/error.rs
Normal file
21
src/error.rs
Normal file
@ -0,0 +1,21 @@
|
||||
#[derive(Debug)]
|
||||
pub enum Error {
|
||||
RLua(rlua::Error),
|
||||
}
|
||||
|
||||
impl From<rlua::Error> for Error {
|
||||
fn from(error: rlua::Error) -> Self {
|
||||
Error::RLua(error)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Error {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let res = match self {
|
||||
Error::RLua(e) => format!("rlua error:\n{:#?}", e),
|
||||
};
|
||||
write!(f, "{}", res)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for Error {}
|
14
src/lib.rs
14
src/lib.rs
@ -1,7 +1,7 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(2 + 2, 4);
|
||||
}
|
||||
}
|
||||
mod searcher;
|
||||
mod error;
|
||||
mod types;
|
||||
|
||||
pub use crate::error::Error;
|
||||
pub use crate::searcher::AddSearcher;
|
||||
pub use crate::types::Result;
|
||||
|
61
src/searcher.rs
Normal file
61
src/searcher.rs
Normal file
@ -0,0 +1,61 @@
|
||||
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 Lua’s
|
||||
/// `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())
|
||||
}
|
||||
}
|
3
src/types.rs
Normal file
3
src/types.rs
Normal file
@ -0,0 +1,3 @@
|
||||
use crate::error::Error;
|
||||
|
||||
pub type Result<A> = std::result::Result<A, Error>;
|
26
tests/tests.rs
Normal file
26
tests/tests.rs
Normal file
@ -0,0 +1,26 @@
|
||||
use rlua::Lua;
|
||||
use rlua_searcher::{AddSearcher, Result};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
let lume = read_lume_to_string();
|
||||
let name = "lume".to_string();
|
||||
let mut map = HashMap::new();
|
||||
map.insert(name, lume);
|
||||
|
||||
let lua = Lua::new();
|
||||
|
||||
let hello = lua
|
||||
.context::<_, Result<String>>(|lua_ctx| {
|
||||
lua_ctx.add_searcher(map)?;
|
||||
Ok(lua_ctx.load(r#"return require("lume")"#).eval()?)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!("hello lume", hello);
|
||||
}
|
||||
|
||||
fn read_lume_to_string() -> String {
|
||||
r#"return "hello lume""#.to_string()
|
||||
}
|
Loading…
Reference in New Issue
Block a user