1use std::collections::HashMap;
2
3use proc_macro_hack::proc_macro_hack;
4use rlua::{Result, Context, UserData, UserDataMethods, MetaMethod, Value, Table, RegistryKey};
5
6#[proc_macro_hack]
11pub use include_lua_macro::include_lua;
12
13pub struct LuaModules {
15 files: HashMap<String, (String, String)>,
16 prefix: String,
17}
18
19impl LuaModules {
20 #[doc(hidden)] pub fn __new(files: HashMap<String, (String, String)>, prefix: &str) -> LuaModules {
22 LuaModules { files: files, prefix: prefix.to_string() }
23 }
24}
25
26pub struct Searcher(LuaModules, RegistryKey);
30
31impl UserData for Searcher {
32 fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) {
33 methods.add_meta_method(MetaMethod::Call, |ctx, this, value: String| {
34 Ok(match this.0.files.get(&value) {
35 Some((source, path)) => {
36 Value::Function(ctx.load(source)
37 .set_name(&format!("{}\\{} (virtual)", &this.0.prefix, path))?
38 .set_environment(ctx.registry_value::<Table>(&this.1)?)?
39 .into_function()?
40 )
41 }
42 None => Value::Nil,
43 })
44 });
45 }
46}
47
48pub trait ContextExt<'a> {
50 fn add_modules(&self, modules: LuaModules) -> Result<()>;
52
53 fn add_modules_with_env(&self, modules: LuaModules, environment: Table<'a>) -> Result<()>;
56
57 fn make_searcher(&self, modules: LuaModules) -> Result<Searcher>;
59
60 fn make_searcher_with_env(&self, modules: LuaModules, environment: Table<'a>) -> Result<Searcher>;
63}
64
65impl<'a> ContextExt<'a> for Context<'a> {
66 fn add_modules(&self, modules: LuaModules) -> Result<()> {
67 self.add_modules_with_env(modules, self.globals())
68 }
69
70 fn add_modules_with_env(&self, modules: LuaModules, environment: Table<'a>) -> Result<()> {
71 let searchers: Table = self.globals().get::<_, Table>("package")?.get("searchers")?;
72 searchers.set(searchers.len()? + 1, self.make_searcher_with_env(modules, environment)?)
73 }
74
75 fn make_searcher(&self, modules: LuaModules) -> Result<Searcher> {
76 self.make_searcher_with_env(modules, self.globals())
77 }
78
79 fn make_searcher_with_env(&self, modules: LuaModules, environment: Table<'a>) -> Result<Searcher> {
80 Ok(Searcher(modules, self.create_registry_value(environment)?))
81 }
82}