bitser icon indicating copy to clipboard operation
bitser copied to clipboard

cdata serialize with __eq metamethod

Open sonoro1234 opened this issue 3 years ago • 5 comments

Hi,

When doing bitser.dumps for a cdata (of type vec2) with __eq methamethod (via metatype) which expects two vec2 to compare I get an error in https://github.com/gvx/bitser/blob/master/bitser.lua#L231 because ffi.typeof(vec2) is not a vec2.

The purpose of https://github.com/gvx/bitser/blob/master/bitser.lua#L231 is to differentiate cdata from ctype and could be perhaps done other way: tostring(cdata_or_ctype):match"^ctype"

sonoro1234 avatar Mar 25 '21 14:03 sonoro1234

Could you provide a minimal code sample that reproduces the problem? That way I can test any potential solution.

I don't think the tostring approach will work, given the LuaJIT documentation:

s = tostring(cdata)

Returns a string representation of the value of 64 bit integers ("nnnLL" or "nnnULL") or complex numbers ("re±imi"). Otherwise returns a string representation of the C type of a ctype object ("ctype<type>") or a cdata object ("cdata<type>: address"), unless you override it with a __tostring metamethod (see ffi.metatype()).

gvx avatar Mar 25 '21 18:03 gvx

It is tostring(ctype) case. I will provide test case tomorrow.

sonoro1234 avatar Mar 25 '21 21:03 sonoro1234

local ffi = require"ffi"
local bitser = require"bitser"

ffi.cdef [[
typedef struct vec2 { double x, y;       } vec2;
]]

local metav2 = {
    __eq = function(a,b) return a.x == b.x and a.y == b.y end,
    __tostring = function(v) return '<'..v.x..','..v.y..'>' end
}
metav2.__index = metav2
local vec2 = ffi.metatype('vec2',metav2)

local a = vec2(1,2)
local b = bitser.loads(bitser.dumps(a))

print(a,b)

It does error. Changing if ty == value then for if tostring(value):match"^ctype" then succeds

sonoro1234 avatar Mar 26 '21 07:03 sonoro1234

My issue with your proposed solution is that it will fail on ctypes with metatables like {__tostring = function(v) return 'ctype object' end}.

What seems to work fine is

local success, eq = pcall(function() return value == ty end)
if success and eq then

I'll add more test cases to the spec, but it seems to work, and the performance impact seems to be minimal.

gvx avatar Mar 31 '21 06:03 gvx

Yes, it works with provided example.

sonoro1234 avatar Mar 31 '21 16:03 sonoro1234