summaryrefslogtreecommitdiff
path: root/src/table.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/table.rs')
-rw-r--r--src/table.rs73
1 files changed, 41 insertions, 32 deletions
diff --git a/src/table.rs b/src/table.rs
index e1c2955..69e8a6d 100644
--- a/src/table.rs
+++ b/src/table.rs
@@ -721,7 +721,6 @@ impl<'lua> Table<'lua> {
TableSequence {
table: self.0,
index: 1,
- len: None,
_phantom: PhantomData,
}
}
@@ -733,17 +732,25 @@ impl<'lua> Table<'lua> {
}
#[cfg(feature = "serialize")]
- pub(crate) fn sequence_values_by_len<V: FromLua<'lua>>(
- self,
- len: Option<usize>,
- ) -> TableSequence<'lua, V> {
- let len = len.unwrap_or_else(|| self.raw_len()) as Integer;
- TableSequence {
- table: self.0,
- index: 1,
- len: Some(len),
- _phantom: PhantomData,
+ pub(crate) fn for_each_value<V>(&self, mut f: impl FnMut(V) -> Result<()>) -> Result<()>
+ where
+ V: FromLua<'lua>,
+ {
+ let lua = self.0.lua;
+ let state = lua.state();
+ unsafe {
+ let _sg = StackGuard::new(state);
+ check_stack(state, 4)?;
+
+ lua.push_ref(&self.0);
+ let len = ffi::lua_rawlen(state, -1);
+ for i in 1..=len {
+ ffi::lua_rawgeti(state, -1, i as _);
+ f(V::from_stack(-1, lua)?)?;
+ ffi::lua_pop(state, 1);
+ }
}
+ Ok(())
}
/// Sets element value at position `idx` without invoking metamethods.
@@ -1085,6 +1092,13 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
use crate::serde::de::{check_value_for_skip, MapPairs};
use crate::value::SerializableValue;
+ let convert_result = |res: Result<()>, serialize_err: Option<S::Error>| match res {
+ Ok(v) => Ok(v),
+ Err(Error::SerializeError(_)) if serialize_err.is_some() => Err(serialize_err.unwrap()),
+ Err(Error::SerializeError(msg)) => Err(serde::ser::Error::custom(msg)),
+ Err(err) => Err(serde::ser::Error::custom(err.to_string())),
+ };
+
let options = self.options;
let visited = &self.visited;
visited.borrow_mut().insert(self.table.to_pointer());
@@ -1093,15 +1107,21 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
let len = self.table.raw_len();
if len > 0 || self.table.is_array() {
let mut seq = serializer.serialize_seq(Some(len))?;
- for value in self.table.clone().sequence_values_by_len::<Value>(None) {
- let value = &value.map_err(serde::ser::Error::custom)?;
- let skip = check_value_for_skip(value, self.options, &self.visited)
- .map_err(serde::ser::Error::custom)?;
+ let mut serialize_err = None;
+ let res = self.table.for_each_value::<Value>(|value| {
+ let skip = check_value_for_skip(&value, self.options, &self.visited)
+ .map_err(|err| Error::SerializeError(err.to_string()))?;
if skip {
- continue;
+ // continue iteration
+ return Ok(());
}
- seq.serialize_element(&SerializableValue::new(value, options, Some(visited)))?;
- }
+ seq.serialize_element(&SerializableValue::new(&value, options, Some(visited)))
+ .map_err(|err| {
+ serialize_err = Some(err);
+ Error::SerializeError(String::new())
+ })
+ });
+ convert_result(res, serialize_err)?;
return seq.end();
}
@@ -1138,18 +1158,7 @@ impl<'a, 'lua> Serialize for SerializableTable<'a, 'lua> {
process_pair(key, value)
})
};
- match res {
- Ok(_) => {}
- Err(Error::SerializeError(_)) if serialize_err.is_some() => {
- return Err(serialize_err.unwrap());
- }
- Err(Error::SerializeError(msg)) => {
- return Err(serde::ser::Error::custom(msg));
- }
- Err(err) => {
- return Err(serde::ser::Error::custom(err.to_string()));
- }
- }
+ convert_result(res, serialize_err)?;
map.end()
}
}
@@ -1219,9 +1228,9 @@ where
///
/// [`Table::sequence_values`]: crate::Table::sequence_values
pub struct TableSequence<'lua, V> {
+ // TODO: Use `&Table`
table: LuaRef<'lua>,
index: Integer,
- len: Option<Integer>,
_phantom: PhantomData<V>,
}
@@ -1242,7 +1251,7 @@ where
lua.push_ref(&self.table);
match ffi::lua_rawgeti(state, -1, self.index) {
- ffi::LUA_TNIL if self.index > self.len.unwrap_or(0) => None,
+ ffi::LUA_TNIL => None,
_ => {
self.index += 1;
Some(V::from_stack(-1, lua))