1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
use mlua::{Error, FromLua, Table};
/// Adds a similar syntax to tables as lua's `require` function.
///
/// # Example
///
/// ```
/// use mlua_extras::{
/// mlua::{Lua, Function},
/// extras::Require,
/// };
///
/// let lua = Lua::new();
///
/// let unpack = lua.require::<Function>("table.unpack")?;
/// ```
///
/// Would be the same as
///
/// ```lua
/// local unpack = require("table").unpack
/// ```
pub trait Require<'lua> {
/// Fetch a nested lua value from the table
fn require<R: FromLua<'lua>>(&'lua self, path: impl AsRef<str>) -> mlua::Result<R>;
}
impl<'lua> Require<'lua> for Table<'lua> {
fn require<R: FromLua<'lua>>(&'lua self, path: impl AsRef<str>) -> mlua::Result<R> {
let segments = path
.as_ref()
.split('.')
.filter_map(|v| (!v.trim().is_empty()).then_some(v.trim()))
.collect::<Vec<_>>();
let mut module = self.clone();
if !segments.is_empty() {
for seg in &segments[..segments.len() - 1] {
module = module.get::<_, Table>(*seg)?;
}
}
match segments.last() {
Some(seg) => module.get::<_, R>(*seg),
None => Err(Error::runtime(format!(
"module not found: {:?}",
path.as_ref()
))),
}
}
}