Documentation updates for new handle behavior, and some minor cleanup
This commit is contained in:
parent
4358034bbf
commit
c6c90f201c
37
README.md
37
README.md
|
@ -6,20 +6,19 @@
|
|||
|
||||
[Guided Tour](examples/guided_tour.rs)
|
||||
|
||||
This library is a high level interface between Rust and Lua. Its major goal is
|
||||
to expose as easy to use, practical, and flexible of an API between Rust and Lua
|
||||
as possible, while also being completely safe.
|
||||
This library is a high level interface between Rust and Lua. Its major goals
|
||||
are to expose as easy to use, practical, and flexible of an API between Rust and
|
||||
Lua as possible, while also being *completely* safe.
|
||||
|
||||
`rlua` is designed around "registry handles" to values inside the Lua state.
|
||||
This means that when you get a type like `rlua::Table` or `rlua::Function` in
|
||||
Rust, what you actually hold is an integer key into the Lua registry. This is
|
||||
different from the bare Lua C API, where you create tables / functions on the
|
||||
Lua stack and must be aware of their stack location. This is also similar to
|
||||
how other Lua bindings systems like
|
||||
[Selene](https://github.com/jeremyong/Selene) for C++ work, but it means that
|
||||
using `rlua` may be slightly slower than what you could conceivably write using
|
||||
the C API. The reasons for this design are safety and flexibility, and to
|
||||
prevent the user of `rlua` from having to be aware of the Lua stack at all.
|
||||
`rlua` is NOT designed to be a perfect zero cost wrapper over the Lua C API,
|
||||
because such a wrapper cannot maintain the safety guarantees that `rlua` is
|
||||
designed to have. Every place where the Lua C API may trigger an error longjmp
|
||||
in any way is protected by `lua_pcall`, and the user of the library is protected
|
||||
from directly interacting with unsafe things like the Lua stack, and there is
|
||||
overhead associated with this safety. However, performance *is* a focus of the
|
||||
library to the extent possible while maintaining safety, so if you encounter
|
||||
something that egregiously worse than using the Lua C API directly, or simply
|
||||
something you feel could perform better, feel free to file a bug report.
|
||||
|
||||
There are currently a few missing pieces of this API:
|
||||
|
||||
|
@ -30,8 +29,7 @@ There are currently a few missing pieces of this API:
|
|||
* "Context" or "Sandboxing" support. There should be the ability to set the
|
||||
`_ENV` upvalue of a loaded chunk to a table other than `_G`, so that you can
|
||||
have different environments for different loaded chunks.
|
||||
* Benchmarks, and quantifying performance differences with what you would
|
||||
might write in C.
|
||||
* Quantifying performance differences to direct use of the Lua C API.
|
||||
|
||||
Additionally, there are ways I would like to change this API, once support lands
|
||||
in rustc. For example:
|
||||
|
@ -40,11 +38,6 @@ in rustc. For example:
|
|||
by macro for tuples up to size 12, it would be great if this was replaced
|
||||
with real variadic generics when this is available in Rust.
|
||||
|
||||
It is also worth it to list some non-goals for the project:
|
||||
|
||||
* Be a perfect zero cost wrapper over the Lua C API
|
||||
* Allow the user to do absolutely everything that the Lua C API might allow
|
||||
|
||||
## API stability
|
||||
|
||||
This library is very much Work In Progress, so there is a some API churn.
|
||||
|
@ -68,11 +61,11 @@ there ARE several internal panics and even aborts in `rlua` source, but they
|
|||
should not be possible to trigger, and if you trigger them this should be
|
||||
considered a bug.
|
||||
|
||||
There are some caveats to the panic / abort guarantee, however:
|
||||
Caveats to the panic / abort guarantee:
|
||||
|
||||
* `rlua` reserves the right to panic on API usage errors. Currently, the only
|
||||
time this will happen is when passed a registry handle type from a different
|
||||
main Lua state.
|
||||
Lua state.
|
||||
* Currently, there are no memory or execution limits on scripts, so untrusted
|
||||
scripts can always at minimum infinite loop or allocate arbitrary amounts of
|
||||
memory.
|
||||
|
|
|
@ -558,7 +558,7 @@ impl Lua {
|
|||
/// [`create_registry_value`]: #method.create_registry_value
|
||||
pub fn registry_value<'lua, T: FromLua<'lua>>(&'lua self, key: &RegistryKey) -> Result<T> {
|
||||
unsafe {
|
||||
if !Arc::ptr_eq(&key.unref_list, &(*self.extra()).registry_unref_list) {
|
||||
if !self.owns_registry_value(key) {
|
||||
return Err(Error::MismatchedRegistryKey);
|
||||
}
|
||||
|
||||
|
@ -585,7 +585,7 @@ impl Lua {
|
|||
/// [`expire_registry_values`]: #method.expire_registry_values
|
||||
pub fn remove_registry_value(&self, key: RegistryKey) -> Result<()> {
|
||||
unsafe {
|
||||
if !Arc::ptr_eq(&key.unref_list, &(*self.extra()).registry_unref_list) {
|
||||
if !self.owns_registry_value(&key) {
|
||||
return Err(Error::MismatchedRegistryKey);
|
||||
}
|
||||
|
||||
|
@ -606,8 +606,9 @@ impl Lua {
|
|||
|
||||
/// Remove any registry values whose `RegistryKey`s have all been dropped.
|
||||
///
|
||||
/// Unlike normal handle values, `RegistryKey`s cannot automatically clean up their registry
|
||||
/// entries on Drop, but you can call this method to remove any unreachable registry values.
|
||||
/// Unlike normal handle values, `RegistryKey`s do not automatically remove themselves on Drop,
|
||||
/// but you can call this method to remove any unreachable registry values not manually removed
|
||||
/// by `Lua::remove_registry_value`.
|
||||
pub fn expire_registry_values(&self) {
|
||||
unsafe {
|
||||
let unref_list = mem::replace(
|
||||
|
|
15
src/types.rs
15
src/types.rs
|
@ -21,17 +21,22 @@ pub(crate) type Callback<'lua, 'a> =
|
|||
|
||||
/// An auto generated key into the Lua registry.
|
||||
///
|
||||
/// This is a handle into a value stored inside the Lua registry, similar to the normal handle types
|
||||
/// like `Table` or `Function`. The difference is that this handle does not require holding a
|
||||
/// reference to a parent `Lua` instance, and thus is managed differently. Though it is more
|
||||
/// difficult to use than the normal handle types, it is Send + Sync + 'static, which means that it
|
||||
/// can be used in many situations where it would be impossible to store a regular handle value.
|
||||
/// This is a handle to a value stored inside the Lua registry. It is not directly usable like the
|
||||
/// `Table` or `Function` handle types, but it is much more flexible and can be used in many
|
||||
/// situations where it is impossible to directly store a normal handle type. It is Send + Sync +
|
||||
/// 'static, and can be used by *any* `Lua` instance as long as it is derived from the same
|
||||
/// underlying main state (such as one received in a Rust callback). It is not automatically
|
||||
/// garbage collected on Drop, but it can be removed with [`Lua::remove_registry_value`], and
|
||||
/// instances not manually removed can be garbage collected with [`Lua::expire_registry_values`].
|
||||
///
|
||||
/// Be warned, If you place this into Lua via a `UserData` type or a rust callback, it is *very
|
||||
/// easy* to accidentally cause reference cycles that the Lua garbage collector cannot resolve.
|
||||
/// Instead of placing a `RegistryKey` into a `UserData` type, prefer instead to use
|
||||
/// `UserData::set_user_value` / `UserData::get_user_value`, and instead of moving a RegistryKey
|
||||
/// into a callback, prefer `Lua::scope`.
|
||||
///
|
||||
/// [`Lua::remove_registry_value`]: struct.Lua.html#method.remove_registry_value
|
||||
/// [`Lua::expire_registry_values`]: struct.Lua.html#method.expire_registry_values
|
||||
pub struct RegistryKey {
|
||||
pub(crate) registry_id: c_int,
|
||||
pub(crate) unref_list: Arc<Mutex<Option<Vec<c_int>>>>,
|
||||
|
|
|
@ -10,7 +10,10 @@ use thread::Thread;
|
|||
use userdata::AnyUserData;
|
||||
use lua::Lua;
|
||||
|
||||
/// A dynamically typed Lua value.
|
||||
/// A dynamically typed Lua value. The `String`, `Table`, `Function`, `Thread`, and `UserData`
|
||||
/// variants contain handle types into the internal Lua state. It is a logic error to mix handle
|
||||
/// types between separate `Lua` instances, or between a parent `Lua` instance and one received as a
|
||||
/// parameter in a Rust callback, and doing so will result in a panic.
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Value<'lua> {
|
||||
/// The Lua value `nil`.
|
||||
|
|
Loading…
Reference in a new issue