Add raw_insert() and raw_remove() for tables (represented as lists)
This commit is contained in:
parent
5eec0ef56b
commit
27121c779d
73
src/table.rs
73
src/table.rs
|
@ -1,7 +1,7 @@
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::os::raw::c_int;
|
use std::os::raw::c_int;
|
||||||
|
|
||||||
use crate::error::Result;
|
use crate::error::{Error, Result};
|
||||||
use crate::ffi;
|
use crate::ffi;
|
||||||
use crate::function::Function;
|
use crate::function::Function;
|
||||||
use crate::types::{Integer, LuaRef};
|
use crate::types::{Integer, LuaRef};
|
||||||
|
@ -222,13 +222,6 @@ impl<'lua> Table<'lua> {
|
||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes a key from the table, returning the value at the key
|
|
||||||
/// if the key was previously in the table.
|
|
||||||
pub fn raw_remove<K: ToLua<'lua>>(&self, key: K) -> Result<()> {
|
|
||||||
self.raw_set(key, Nil)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Sets a key-value pair without invoking metamethods.
|
/// Sets a key-value pair without invoking metamethods.
|
||||||
pub fn raw_set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
pub fn raw_set<K: ToLua<'lua>, V: ToLua<'lua>>(&self, key: K, value: V) -> Result<()> {
|
||||||
let lua = self.0.lua;
|
let lua = self.0.lua;
|
||||||
|
@ -269,6 +262,70 @@ impl<'lua> Table<'lua> {
|
||||||
V::from_lua(value, lua)
|
V::from_lua(value, lua)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserts element value at position idx to the table, shifting up the elements from table[idx].
|
||||||
|
/// The worst case complexity is O(n), where n is the table length.
|
||||||
|
pub fn raw_insert<V: ToLua<'lua>>(&self, idx: Integer, value: V) -> Result<()> {
|
||||||
|
let lua = self.0.lua;
|
||||||
|
let size = self.raw_len();
|
||||||
|
if idx < 1 || idx > size + 1 {
|
||||||
|
return Err(Error::RuntimeError("index out of bounds".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = value.to_lua(lua)?;
|
||||||
|
unsafe {
|
||||||
|
let _sg = StackGuard::new(lua.state);
|
||||||
|
assert_stack(lua.state, 6);
|
||||||
|
|
||||||
|
lua.push_ref(&self.0);
|
||||||
|
lua.push_value(value)?;
|
||||||
|
|
||||||
|
protect_lua_closure(lua.state, 2, 0, |state| {
|
||||||
|
for i in (idx..size + 1).rev() {
|
||||||
|
// table[i+1] = table[i]
|
||||||
|
ffi::lua_rawgeti(state, -2, i);
|
||||||
|
ffi::lua_rawseti(state, -3, i + 1);
|
||||||
|
}
|
||||||
|
ffi::lua_rawseti(state, -2, idx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes a key from the table.
|
||||||
|
///
|
||||||
|
/// If `key` is an integer, mlua shifts down the elements from table[key+1],
|
||||||
|
/// and erases element table[key]. The complexity is O(n) in worst case,
|
||||||
|
/// where n is the table length.
|
||||||
|
///
|
||||||
|
/// For othey key types this is equivalent to setting table[key] = nil.
|
||||||
|
pub fn raw_remove<K: ToLua<'lua>>(&self, key: K) -> Result<()> {
|
||||||
|
let lua = self.0.lua;
|
||||||
|
let key = key.to_lua(lua)?;
|
||||||
|
match key {
|
||||||
|
Value::Integer(idx) => {
|
||||||
|
let size = self.raw_len();
|
||||||
|
if idx < 1 || idx > size {
|
||||||
|
return Err(Error::RuntimeError("index out of bounds".to_string()));
|
||||||
|
}
|
||||||
|
unsafe {
|
||||||
|
let _sg = StackGuard::new(lua.state);
|
||||||
|
assert_stack(lua.state, 6);
|
||||||
|
|
||||||
|
lua.push_ref(&self.0);
|
||||||
|
|
||||||
|
protect_lua_closure(lua.state, 1, 0, |state| {
|
||||||
|
for i in idx..size {
|
||||||
|
ffi::lua_rawgeti(state, -1, i + 1);
|
||||||
|
ffi::lua_rawseti(state, -2, i);
|
||||||
|
}
|
||||||
|
ffi::lua_pushnil(state);
|
||||||
|
ffi::lua_rawseti(state, -2, size);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => self.raw_set(key, Nil),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the result of the Lua `#` operator.
|
/// Returns the result of the Lua `#` operator.
|
||||||
///
|
///
|
||||||
/// This might invoke the `__len` metamethod. Use the [`raw_len`] method if that is not desired.
|
/// This might invoke the `__len` metamethod. Use the [`raw_len`] method if that is not desired.
|
||||||
|
|
|
@ -16,6 +16,7 @@ use mlua::{Lua, Result, UserData};
|
||||||
#[test]
|
#[test]
|
||||||
fn test_gc_control() -> Result<()> {
|
fn test_gc_control() -> Result<()> {
|
||||||
let lua = Lua::new();
|
let lua = Lua::new();
|
||||||
|
let globals = lua.globals();
|
||||||
|
|
||||||
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
#[cfg(any(feature = "lua53", feature = "lua52"))]
|
||||||
{
|
{
|
||||||
|
@ -30,9 +31,8 @@ fn test_gc_control() -> Result<()> {
|
||||||
impl UserData for MyUserdata {}
|
impl UserData for MyUserdata {}
|
||||||
|
|
||||||
let rc = Arc::new(());
|
let rc = Arc::new(());
|
||||||
lua.globals()
|
globals.set("userdata", lua.create_userdata(MyUserdata(rc.clone()))?)?;
|
||||||
.set("userdata", lua.create_userdata(MyUserdata(rc.clone()))?)?;
|
globals.raw_remove("userdata")?;
|
||||||
lua.globals().raw_remove("userdata")?;
|
|
||||||
|
|
||||||
assert_eq!(Arc::strong_count(&rc), 2);
|
assert_eq!(Arc::strong_count(&rc), 2);
|
||||||
lua.gc_collect()?;
|
lua.gc_collect()?;
|
||||||
|
|
|
@ -91,10 +91,32 @@ fn test_table() -> Result<()> {
|
||||||
globals.set("table4", lua.create_sequence_from(vec![1, 2, 3, 4, 5])?)?;
|
globals.set("table4", lua.create_sequence_from(vec![1, 2, 3, 4, 5])?)?;
|
||||||
let table4 = globals.get::<_, Table>("table4")?;
|
let table4 = globals.get::<_, Table>("table4")?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
table4.pairs().collect::<Result<Vec<(i64, i64)>>>()?,
|
table4
|
||||||
|
.clone()
|
||||||
|
.pairs()
|
||||||
|
.collect::<Result<Vec<(i64, i64)>>>()?,
|
||||||
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
vec![(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
|
||||||
);
|
);
|
||||||
|
|
||||||
|
table4.raw_insert(4, 35)?;
|
||||||
|
table4.raw_insert(7, 7)?;
|
||||||
|
assert_eq!(
|
||||||
|
table4
|
||||||
|
.clone()
|
||||||
|
.pairs()
|
||||||
|
.collect::<Result<Vec<(i64, i64)>>>()?,
|
||||||
|
vec![(1, 1), (2, 2), (3, 3), (4, 35), (5, 4), (6, 5), (7, 7)]
|
||||||
|
);
|
||||||
|
|
||||||
|
table4.raw_remove(1)?;
|
||||||
|
assert_eq!(
|
||||||
|
table4
|
||||||
|
.clone()
|
||||||
|
.pairs()
|
||||||
|
.collect::<Result<Vec<(i64, i64)>>>()?,
|
||||||
|
vec![(1, 2), (2, 3), (3, 35), (4, 4), (5, 5), (6, 7)]
|
||||||
|
);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue