Do not consume self in Table::pairs and Table::sequence_values methods.

This commit is contained in:
Alex Orlenko
2024-07-10 23:09:54 +01:00
parent cd3f45f31f
commit c715aec1f7
3 changed files with 39 additions and 54 deletions
+12 -12
View File
@@ -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
View File
@@ -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
View File
@@ -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,
{