Skip to content

add load_from_std_lib function to Lua state #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ cc = { version = "1.0", optional = true }
pkg-config = { version = "0.3.11", optional = true }

[dev-dependencies]
rustyline = "3.0.0"
rustyline = "5.0"
criterion = "0.2.0"
compiletest_rs = { version = "0.3", features = ["stable"] }

Expand Down
121 changes: 80 additions & 41 deletions src/lua.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,42 @@ impl Lua {
create_lua(lua_mod)
}

/// Loads the specified set of safe standard libraries into an existing Lua state.
///
/// Use the [`StdLib`] flags to specifiy the libraries you want to load.
///
/// Note that the `debug` library can't be loaded using this function as it can be used to break
/// the safety guarantees of rlua. If you really want to load it, use the sister function
/// [`Lua::unsafe_load_from_std_lib`].
///
/// # Panics
///
/// Panics if `lua_mod` contains `StdLib::DEBUG`
pub fn load_from_std_lib(&self, lua_mod: StdLib) -> Result<()> {
assert!(
!lua_mod.contains(StdLib::DEBUG),
"The lua debug module can't be loaded using `load_from_std_lib`. Use `unsafe_load_from_std_lib` instead."
);

unsafe {
protect_lua_closure(self.main_state, 0, 0, |state| {
load_from_std_lib(state, lua_mod);
})
}
}

/// Loads the specified set of standard libraries into an existing Lua state.
///
/// Use the [`StdLib`] flags to specifiy the libraries you want to load.
///
/// This function is unsafe because it can be used to load the `debug` library which can be used
/// to break the safety guarantees provided by rlua.
pub unsafe fn unsafe_load_from_std_lib(&self, lua_mod: StdLib) -> Result<()> {
protect_lua_closure(self.main_state, 0, 0, |state| {
load_from_std_lib(state, lua_mod);
})
}

/// The main entry point of the rlua API.
///
/// In order to create Lua values, load and execute Lua code, or otherwise interact with the Lua
Expand Down Expand Up @@ -414,47 +450,7 @@ unsafe fn create_lua(lua_mod_to_load: StdLib) -> Lua {

extra.ref_thread = rlua_expect!(
protect_lua_closure(state, 0, 0, |state| {
// Do not open the debug library, it can be used to cause unsafety.
if lua_mod_to_load.contains(StdLib::BASE) {
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::COROUTINE) {
ffi::luaL_requiref(state, cstr!("coroutine"), ffi::luaopen_coroutine, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::TABLE) {
ffi::luaL_requiref(state, cstr!("table"), ffi::luaopen_table, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::IO) {
ffi::luaL_requiref(state, cstr!("io"), ffi::luaopen_io, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::OS) {
ffi::luaL_requiref(state, cstr!("os"), ffi::luaopen_os, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::STRING) {
ffi::luaL_requiref(state, cstr!("string"), ffi::luaopen_string, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::UTF8) {
ffi::luaL_requiref(state, cstr!("utf8"), ffi::luaopen_utf8, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::MATH) {
ffi::luaL_requiref(state, cstr!("math"), ffi::luaopen_math, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::PACKAGE) {
ffi::luaL_requiref(state, cstr!("package"), ffi::luaopen_package, 1);
ffi::lua_pop(state, 1);
}
if lua_mod_to_load.contains(StdLib::DEBUG) {
ffi::luaL_requiref(state, cstr!("debug"), ffi::luaopen_debug, 1);
ffi::lua_pop(state, 1);
}
load_from_std_lib(state, lua_mod_to_load);

init_error_registry(state);

Expand Down Expand Up @@ -513,4 +509,47 @@ unsafe fn create_lua(lua_mod_to_load: StdLib) -> Lua {
}
}

unsafe fn load_from_std_lib(state: *mut ffi::lua_State, lua_mod: StdLib) {
if lua_mod.contains(StdLib::BASE) {
ffi::luaL_requiref(state, cstr!("_G"), ffi::luaopen_base, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::COROUTINE) {
ffi::luaL_requiref(state, cstr!("coroutine"), ffi::luaopen_coroutine, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::TABLE) {
ffi::luaL_requiref(state, cstr!("table"), ffi::luaopen_table, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::IO) {
ffi::luaL_requiref(state, cstr!("io"), ffi::luaopen_io, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::OS) {
ffi::luaL_requiref(state, cstr!("os"), ffi::luaopen_os, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::STRING) {
ffi::luaL_requiref(state, cstr!("string"), ffi::luaopen_string, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::UTF8) {
ffi::luaL_requiref(state, cstr!("utf8"), ffi::luaopen_utf8, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::MATH) {
ffi::luaL_requiref(state, cstr!("math"), ffi::luaopen_math, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::PACKAGE) {
ffi::luaL_requiref(state, cstr!("package"), ffi::luaopen_package, 1);
ffi::lua_pop(state, 1);
}
if lua_mod.contains(StdLib::DEBUG) {
ffi::luaL_requiref(state, cstr!("debug"), ffi::luaopen_debug, 1);
ffi::lua_pop(state, 1);
}
}

pub(crate) static FUNCTION_METATABLE_REGISTRY_KEY: u8 = 0;
2 changes: 1 addition & 1 deletion tests/compile-fail/scope_invariance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ fn main() {

scope
.create_function_mut(|_, ()| {
//~^ error: closure may outlive the current function, but it borrows `test`, which is owned by the current function
test.field = 42;
//~^ error: `test` does not live long enough
Ok(())
})
.unwrap()
Expand Down
2 changes: 1 addition & 1 deletion tests/compile-fail/scope_mutable_aliasing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ fn main() {
lua.scope(|scope| {
let a = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap();
let b = scope.create_nonstatic_userdata(MyUserData(&mut i)).unwrap();
//~^ error: cannot borrow `*i` as mutable more than once at a time
//~^ error: cannot borrow `i` as mutable more than once at a time
});
});
}