@@ -1184,7 +1184,7 @@ pub const Lua = opaque {
11841184 /// Stack Behavior: `[-1, +0, -]`
11851185 pub fn setMetatable (lua : * Lua , index : i32 ) void {
11861186 lua .validateStackIndex (index );
1187- assert (lua .isTable (index ));
1187+ assert (lua .isTable (-1 ));
11881188
11891189 const res = c .lua_setmetatable (asState (lua ), index );
11901190 assert (1 == res );
@@ -2289,7 +2289,7 @@ pub const Lua = opaque {
22892289 /// Refer to: https://www.lua.org/manual/5.1/manual.html#luaL_checkudata
22902290 /// Stack Behavior: `[-0, +0, v]`
22912291 pub fn checkUserdata (lua : * Lua , arg_n : i32 , type_name : [:0 ]const u8 ) ? * anyopaque {
2292- return c .luaL_checkudata (asState (lua ), arg_n , @ptrCast ( type_name .ptr ) );
2292+ return c .luaL_checkudata (asState (lua ), arg_n , type_name .ptr );
22932293 }
22942294
22952295 /// Used by C functions to validate received arguments.
@@ -4438,6 +4438,57 @@ test "checkArgument() should return error when argument is invalid and succeed w
44384438 try std .testing .expectEqualSlices (u8 , "bad argument #1 to '?' (FOOBAR)" , message );
44394439}
44404440
4441+ test "checkUserdata() will accept user data with the correct metatable type" {
4442+ const lua = try Lua .init (std .testing .allocator );
4443+ defer lua .deinit ();
4444+
4445+ const T = struct {
4446+ fn EchoUserdata (l : * Lua ) callconv (.c ) i32 {
4447+ const val = l .checkUserdata (1 , "MyUserdataType" );
4448+ l .pushLightUserdata (val );
4449+ return 1 ;
4450+ }
4451+ };
4452+
4453+ lua .pushCFunction (T .EchoUserdata );
4454+
4455+ const expected = lua .newUserdata (32 );
4456+ try std .testing .expect (lua .newMetatable ("MyUserdataType" ));
4457+ lua .setMetatable (-2 );
4458+ try std .testing .expectEqual (2 , lua .getTop ());
4459+ try std .testing .expect (lua .isFunction (1 ));
4460+ try std .testing .expect (lua .isUserdata (2 ));
4461+
4462+ try lua .callProtected (1 , 1 , 0 );
4463+
4464+ try std .testing .expectEqual (1 , lua .getTop ());
4465+ try std .testing .expect (lua .isUserdata (-1 ));
4466+ try std .testing .expectEqual (expected , lua .toUserdata (-1 ));
4467+ }
4468+
4469+ test "checkUserdata() will reject user data with the wrong metatable type" {
4470+ const lua = try Lua .init (std .testing .allocator );
4471+ defer lua .deinit ();
4472+
4473+ const T = struct {
4474+ fn EchoUserdata (l : * Lua ) callconv (.c ) i32 {
4475+ const val = l .checkUserdata (1 , "MyUserdataType" );
4476+ l .pushLightUserdata (val );
4477+ return 1 ;
4478+ }
4479+ };
4480+
4481+ lua .pushCFunction (T .EchoUserdata );
4482+
4483+ _ = lua .newUserdata (32 );
4484+ try std .testing .expectEqual (2 , lua .getTop ());
4485+ try std .testing .expect (lua .isFunction (1 ));
4486+ try std .testing .expect (lua .isUserdata (2 ));
4487+
4488+ try std .testing .expectError (error .Runtime , lua .callProtected (1 , 1 , 0 ));
4489+ try std .testing .expectEqualStrings ("bad argument #1 to '?' (MyUserdataType expected, got userdata)" , try lua .toLString (-1 ));
4490+ }
4491+
44414492test "checkArgument() should return handle null message" {
44424493 const lua = try Lua .init (std .testing .allocator );
44434494 defer lua .deinit ();
0 commit comments