mirror of
https://github.com/mlua-rs/mlua
synced 2026-06-08 16:05:43 +00:00
Do not consume self in Table::pairs and Table::sequence_values methods.
This commit is contained in:
+12
-12
@@ -302,7 +302,7 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
|
||||
let _guard = RecursionGuard::new(&t, &self.visited);
|
||||
|
||||
let mut deserializer = MapDeserializer {
|
||||
pairs: MapPairs::new(t, self.options.sort_keys)?,
|
||||
pairs: MapPairs::new(&t, self.options.sort_keys)?,
|
||||
value: None,
|
||||
options: self.options,
|
||||
visited: self.visited,
|
||||
@@ -383,13 +383,13 @@ impl<'de> serde::Deserializer<'de> for Deserializer {
|
||||
}
|
||||
}
|
||||
|
||||
struct SeqDeserializer {
|
||||
seq: TableSequence<Value>,
|
||||
struct SeqDeserializer<'a> {
|
||||
seq: TableSequence<'a, Value>,
|
||||
options: Options,
|
||||
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
|
||||
}
|
||||
|
||||
impl<'de> de::SeqAccess<'de> for SeqDeserializer {
|
||||
impl<'de> de::SeqAccess<'de> for SeqDeserializer<'_> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
@@ -454,13 +454,13 @@ impl<'de> de::SeqAccess<'de> for VecDeserializer {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) enum MapPairs {
|
||||
Iter(TablePairs<Value, Value>),
|
||||
pub(crate) enum MapPairs<'a> {
|
||||
Iter(TablePairs<'a, Value, Value>),
|
||||
Vec(Vec<(Value, Value)>),
|
||||
}
|
||||
|
||||
impl MapPairs {
|
||||
pub(crate) fn new(t: Table, sort_keys: bool) -> Result<Self> {
|
||||
impl<'a> MapPairs<'a> {
|
||||
pub(crate) fn new(t: &'a Table, sort_keys: bool) -> Result<Self> {
|
||||
if sort_keys {
|
||||
let mut pairs = t.pairs::<Value, Value>().collect::<Result<Vec<_>>>()?;
|
||||
pairs.sort_by(|(a, _), (b, _)| b.cmp(a)); // reverse order as we pop values from the end
|
||||
@@ -485,7 +485,7 @@ impl MapPairs {
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for MapPairs {
|
||||
impl Iterator for MapPairs<'_> {
|
||||
type Item = Result<(Value, Value)>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
@@ -496,15 +496,15 @@ impl Iterator for MapPairs {
|
||||
}
|
||||
}
|
||||
|
||||
struct MapDeserializer {
|
||||
pairs: MapPairs,
|
||||
struct MapDeserializer<'a> {
|
||||
pairs: MapPairs<'a>,
|
||||
value: Option<Value>,
|
||||
options: Options,
|
||||
visited: Rc<RefCell<FxHashSet<*const c_void>>>,
|
||||
processed: usize,
|
||||
}
|
||||
|
||||
impl<'de> de::MapAccess<'de> for MapDeserializer {
|
||||
impl<'de> de::MapAccess<'de> for MapDeserializer<'_> {
|
||||
type Error = Error;
|
||||
|
||||
fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>>
|
||||
|
||||
+23
-38
@@ -13,6 +13,7 @@ use {
|
||||
use crate::error::{Error, Result};
|
||||
use crate::function::Function;
|
||||
use crate::private::Sealed;
|
||||
use crate::state::{LuaGuard, RawLua};
|
||||
use crate::types::{Integer, ValueRef};
|
||||
use crate::util::{assert_stack, check_stack, StackGuard};
|
||||
use crate::value::{FromLua, FromLuaMulti, IntoLua, IntoLuaMulti, Nil, Value};
|
||||
@@ -580,18 +581,12 @@ impl Table {
|
||||
self.0.to_pointer()
|
||||
}
|
||||
|
||||
/// Consume this table and return an iterator over the pairs of the table.
|
||||
/// Returns an iterator over the pairs of the table.
|
||||
///
|
||||
/// This works like the Lua `pairs` function, but does not invoke the `__pairs` metamethod.
|
||||
///
|
||||
/// The pairs are wrapped in a [`Result`], since they are lazily converted to `K` and `V` types.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// While this method consumes the `Table` object, it can not prevent code from mutating the
|
||||
/// table while the iteration is in progress. Refer to the [Lua manual] for information about
|
||||
/// the consequences of such mutation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Iterate over all globals:
|
||||
@@ -613,9 +608,10 @@ impl Table {
|
||||
///
|
||||
/// [`Result`]: crate::Result
|
||||
/// [Lua manual]: http://www.lua.org/manual/5.4/manual.html#pdf-next
|
||||
pub fn pairs<K: FromLua, V: FromLua>(self) -> TablePairs<K, V> {
|
||||
pub fn pairs<K: FromLua, V: FromLua>(&self) -> TablePairs<K, V> {
|
||||
TablePairs {
|
||||
table: self.0,
|
||||
guard: self.0.lua.lock(),
|
||||
table: self,
|
||||
key: Some(Nil),
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
@@ -649,18 +645,12 @@ impl Table {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Consume this table and return an iterator over all values in the sequence part of the table.
|
||||
/// Returns an iterator over all values in the sequence part of the table.
|
||||
///
|
||||
/// The iterator will yield all values `t[1]`, `t[2]` and so on, until a `nil` value is
|
||||
/// encountered. This mirrors the behavior of Lua's `ipairs` function but does not invoke
|
||||
/// any metamethods.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// While this method consumes the `Table` object, it can not prevent code from mutating the
|
||||
/// table while the iteration is in progress. Refer to the [Lua manual] for information about
|
||||
/// the consequences of such mutation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
@@ -687,20 +677,15 @@ impl Table {
|
||||
/// [`pairs`]: #method.pairs
|
||||
/// [`Result`]: crate::Result
|
||||
/// [Lua manual]: http://www.lua.org/manual/5.4/manual.html#pdf-next
|
||||
pub fn sequence_values<V: FromLua>(self) -> TableSequence<V> {
|
||||
pub fn sequence_values<V: FromLua>(&self) -> TableSequence<V> {
|
||||
TableSequence {
|
||||
table: self.0,
|
||||
guard: self.0.lua.lock(),
|
||||
table: self,
|
||||
index: 1,
|
||||
_phantom: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[deprecated(since = "0.9.0", note = "use `sequence_values` instead")]
|
||||
pub fn raw_sequence_values<V: FromLua>(self) -> TableSequence<V> {
|
||||
self.sequence_values()
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
pub(crate) fn for_each_value<V>(&self, mut f: impl FnMut(V) -> Result<()>) -> Result<()>
|
||||
where
|
||||
@@ -782,9 +767,8 @@ impl Table {
|
||||
) -> fmt::Result {
|
||||
visited.insert(self.to_pointer());
|
||||
|
||||
let t = self.clone();
|
||||
// Collect key/value pairs into a vector so we can sort them
|
||||
let mut pairs = t.pairs::<Value, Value>().flatten().collect::<Vec<_>>();
|
||||
let mut pairs = self.pairs::<Value, Value>().flatten().collect::<Vec<_>>();
|
||||
// Sort keys
|
||||
pairs.sort_by(|(a, _), (b, _)| a.cmp(b));
|
||||
if pairs.is_empty() {
|
||||
@@ -1111,7 +1095,7 @@ impl<'a> Serialize for SerializableTable<'a> {
|
||||
// Fast track
|
||||
self.table.for_each(process_pair)
|
||||
} else {
|
||||
MapPairs::new(self.table.clone(), self.options.sort_keys)
|
||||
MapPairs::new(self.table, self.options.sort_keys)
|
||||
.map_err(serde::ser::Error::custom)?
|
||||
.try_for_each(|kv| {
|
||||
let (key, value) = kv?;
|
||||
@@ -1128,13 +1112,14 @@ impl<'a> Serialize for SerializableTable<'a> {
|
||||
/// This struct is created by the [`Table::pairs`] method.
|
||||
///
|
||||
/// [`Table::pairs`]: crate::Table::pairs
|
||||
pub struct TablePairs<K, V> {
|
||||
table: ValueRef,
|
||||
pub struct TablePairs<'a, K, V> {
|
||||
guard: LuaGuard,
|
||||
table: &'a Table,
|
||||
key: Option<Value>,
|
||||
_phantom: PhantomData<(K, V)>,
|
||||
}
|
||||
|
||||
impl<K, V> Iterator for TablePairs<K, V>
|
||||
impl<'a, K, V> Iterator for TablePairs<'a, K, V>
|
||||
where
|
||||
K: FromLua,
|
||||
V: FromLua,
|
||||
@@ -1143,14 +1128,14 @@ where
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(prev_key) = self.key.take() {
|
||||
let lua = self.table.lua.lock();
|
||||
let lua: &RawLua = &self.guard;
|
||||
let state = lua.state();
|
||||
|
||||
let res = (|| unsafe {
|
||||
let _sg = StackGuard::new(state);
|
||||
check_stack(state, 5)?;
|
||||
|
||||
lua.push_ref(&self.table);
|
||||
lua.push_ref(&self.table.0);
|
||||
lua.push_value(&prev_key)?;
|
||||
|
||||
// It must be safe to call `lua_next` unprotected as deleting a key from a table is
|
||||
@@ -1187,21 +1172,21 @@ where
|
||||
/// This struct is created by the [`Table::sequence_values`] method.
|
||||
///
|
||||
/// [`Table::sequence_values`]: crate::Table::sequence_values
|
||||
pub struct TableSequence<V> {
|
||||
// TODO: Use `&Table`
|
||||
table: ValueRef,
|
||||
pub struct TableSequence<'a, V> {
|
||||
guard: LuaGuard,
|
||||
table: &'a Table,
|
||||
index: Integer,
|
||||
_phantom: PhantomData<V>,
|
||||
}
|
||||
|
||||
impl<V> Iterator for TableSequence<V>
|
||||
impl<'a, V> Iterator for TableSequence<'a, V>
|
||||
where
|
||||
V: FromLua,
|
||||
{
|
||||
type Item = Result<V>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let lua = self.table.lua.lock();
|
||||
let lua: &RawLua = &self.guard;
|
||||
let state = lua.state();
|
||||
unsafe {
|
||||
let _sg = StackGuard::new(state);
|
||||
@@ -1209,7 +1194,7 @@ where
|
||||
return Some(Err(err));
|
||||
}
|
||||
|
||||
lua.push_ref(&self.table);
|
||||
lua.push_ref(&self.table.0);
|
||||
match ffi::lua_rawgeti(state, -1, self.index) {
|
||||
ffi::LUA_TNIL => None,
|
||||
_ => {
|
||||
|
||||
+4
-4
@@ -1089,12 +1089,12 @@ impl UserDataMetatable {
|
||||
self.0.contains_key(MetaMethod::validate(key.as_ref())?)
|
||||
}
|
||||
|
||||
/// Consumes this metatable and returns an iterator over the pairs of the metatable.
|
||||
/// Returns an iterator over the pairs of the metatable.
|
||||
///
|
||||
/// The pairs are wrapped in a [`Result`], since they are lazily converted to `V` type.
|
||||
///
|
||||
/// [`Result`]: crate::Result
|
||||
pub fn pairs<V: FromLua>(self) -> UserDataMetatablePairs<V> {
|
||||
pub fn pairs<V: FromLua>(&self) -> UserDataMetatablePairs<V> {
|
||||
UserDataMetatablePairs(self.0.pairs())
|
||||
}
|
||||
}
|
||||
@@ -1107,9 +1107,9 @@ impl UserDataMetatable {
|
||||
///
|
||||
/// [`UserData`]: crate::UserData
|
||||
/// [`UserDataMetatable::pairs`]: crate::UserDataMetatable::method.pairs
|
||||
pub struct UserDataMetatablePairs<V>(TablePairs<StdString, V>);
|
||||
pub struct UserDataMetatablePairs<'a, V>(TablePairs<'a, StdString, V>);
|
||||
|
||||
impl<V> Iterator for UserDataMetatablePairs<V>
|
||||
impl<'a, V> Iterator for UserDataMetatablePairs<'a, V>
|
||||
where
|
||||
V: FromLua,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user