@@ -341,6 +341,54 @@ impl Table {
341341 }
342342 }
343343
344+ /// Removes a key from the table.
345+ ///
346+ /// If `key` is an integer, mlua shifts down the elements from `table[key+1]`,
347+ /// and erases element `table[key]`. The complexity is `O(n)` in the worst case,
348+ /// where `n` is the table length.
349+ ///
350+ /// For other key types this is equivalent to setting `table[key] = nil`.
351+ ///
352+ /// This might invoke the `__len`, `__index` and `__newindex` metamethods.
353+ /// Use the [`raw_remove`] method if that is not desired.
354+ ///
355+ /// [`raw_remove`]: Table::raw_remove
356+ pub fn remove ( & self , key : impl IntoLua ) -> Result < ( ) > {
357+ // Fast track (skip protected call)
358+ if !self . has_metatable ( ) {
359+ return self . raw_remove ( key) ;
360+ }
361+
362+ let lua = self . 0 . lua . lock ( ) ;
363+ let key = key. into_lua ( lua. lua ( ) ) ?;
364+ match key {
365+ Value :: Integer ( idx) => {
366+ let size = self . len ( ) ?;
367+ if idx < 1 || idx > size {
368+ return Err ( Error :: runtime ( "index out of bounds" ) ) ;
369+ }
370+
371+ let state = lua. state ( ) ;
372+ unsafe {
373+ let _sg = StackGuard :: new ( state) ;
374+ check_stack ( state, 4 ) ?;
375+
376+ lua. push_ref ( & self . 0 ) ;
377+ protect_lua ! ( state, 1 , 0 , |state| {
378+ for i in idx..size {
379+ // table[i] = table[i+1]
380+ ffi:: lua_geti( state, -1 , i + 1 ) ;
381+ ffi:: lua_seti( state, -2 , i) ;
382+ }
383+ ffi:: lua_pushnil( state) ;
384+ ffi:: lua_seti( state, -2 , size) ;
385+ } )
386+ }
387+ }
388+ _ => self . set ( key, Nil ) ,
389+ }
390+ }
391+
344392 /// Compares two tables for equality.
345393 ///
346394 /// Tables are compared by reference first.
0 commit comments