From c2bfc9ec52c5cdcfa37dd6e39e4fd5c032568a62 Mon Sep 17 00:00:00 2001 From: Alex Orlenko Date: Mon, 19 Jun 2023 23:28:08 +0100 Subject: [PATCH] Implement `PartialEq<[T]>` for tables --- src/table.rs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ tests/table.rs | 49 +++++++++++++++---------------------------------- 2 files changed, 65 insertions(+), 34 deletions(-) diff --git a/src/table.rs b/src/table.rs index fdcbfe7..e87ecc9 100644 --- a/src/table.rs +++ b/src/table.rs @@ -797,6 +797,56 @@ impl<'lua> AsRef> for Table<'lua> { } } +impl<'lua, T> PartialEq<[T]> for Table<'lua> +where + T: IntoLua<'lua> + Clone, +{ + fn eq(&self, other: &[T]) -> bool { + let lua = self.0.lua; + let state = lua.state(); + unsafe { + let _sg = StackGuard::new(state); + assert_stack(state, 4); + + lua.push_ref(&self.0); + + let len = ffi::lua_rawlen(state, -1) as usize; + for i in 0..len { + ffi::lua_rawgeti(state, -1, (i + 1) as _); + let val = lua.pop_value(); + if val == Nil { + return i == other.len(); + } + match other.get(i).map(|v| v.clone().into_lua(lua)) { + Some(Ok(other_val)) if val == other_val => continue, + _ => return false, + } + } + } + true + } +} + +impl<'lua, T> PartialEq<&[T]> for Table<'lua> +where + T: IntoLua<'lua> + Clone, +{ + #[inline] + fn eq(&self, other: &&[T]) -> bool { + self == *other + } +} + +impl<'lua, T, const N: usize> PartialEq<[T; N]> for Table<'lua> +where + T: IntoLua<'lua> + Clone, +{ + #[inline] + fn eq(&self, other: &[T; N]) -> bool { + self == &other[..] + } +} + /// An extension trait for `Table`s that provides a variety of convenient functionality. pub trait TableExt<'lua>: Sealed { /// Calls the table as function assuming it has `__call` metamethod. diff --git a/tests/table.rs b/tests/table.rs index c71b5a3..69c7ede 100644 --- a/tests/table.rs +++ b/tests/table.rs @@ -57,6 +57,7 @@ fn test_table() -> Result<()> { .collect::>>()?, vec![1, 2, 3, 4, 5] ); + assert_eq!(table1, [1, 2, 3, 4, 5]); assert_eq!(table2.len()?, 0); assert_eq!( @@ -66,12 +67,10 @@ fn test_table() -> Result<()> { .collect::>>()?, vec![] ); - assert_eq!( - table2.sequence_values().collect::>>()?, - vec![] - ); + assert_eq!(table2, [0; 0]); // sequence_values should only iterate until the first border + assert_eq!(table3, [1, 2]); assert_eq!( table3.sequence_values().collect::>>()?, vec![1, 2] @@ -116,17 +115,12 @@ fn test_table_push_pop() -> Result<()> { // Test raw access let table1 = lua.create_sequence_from(vec![123])?; table1.raw_push(321)?; - assert_eq!( - table1 - .clone() - .raw_sequence_values::() - .collect::>>()?, - vec![123, 321] - ); + assert_eq!(table1, [123, 321]); assert_eq!(table1.raw_pop::()?, 321); assert_eq!(table1.raw_pop::()?, 123); assert_eq!(table1.raw_pop::()?, Value::Nil); // An extra pop should do nothing assert_eq!(table1.raw_len(), 0); + assert_eq!(table1, [0; 0]); // Test access through metamethods let table2 = lua @@ -144,6 +138,13 @@ fn test_table_push_pop() -> Result<()> { .eval::()?; table2.push(345)?; assert_eq!(table2.len()?, 2); + assert_eq!( + table2 + .clone() + .raw_sequence_values::() + .collect::>>()?, + vec![] + ); assert_eq!(table2.pop::()?, 345); assert_eq!(table2.pop::()?, 234); assert_eq!(table2.pop::()?, Value::Nil); @@ -205,29 +206,9 @@ fn test_table_sequence_from() -> Result<()> { let get_table = lua.create_function(|_, t: Table| Ok(t))?; - assert_eq!( - get_table - .call::<_, Table>(vec![1, 2, 3])? - .sequence_values() - .collect::>>()?, - vec![1, 2, 3] - ); - - assert_eq!( - get_table - .call::<_, Table>([1, 2, 3].as_ref())? - .sequence_values() - .collect::>>()?, - vec![1, 2, 3] - ); - - assert_eq!( - get_table - .call::<_, Table>([1, 2, 3])? - .sequence_values() - .collect::>>()?, - vec![1, 2, 3] - ); + assert_eq!(get_table.call::<_, Table>(vec![1, 2, 3])?, [1, 2, 3]); + assert_eq!(get_table.call::<_, Table>([4, 5, 6])?, [4, 5, 6]); + assert_eq!(get_table.call::<_, Table>([7, 8, 9].as_slice())?, [7, 8, 9]); Ok(()) }