bitser
bitser copied to clipboard
cdata serialize with __eq metamethod
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"
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 (seeffi.metatype()
).
It is tostring(ctype) case. I will provide test case tomorrow.
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
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.
Yes, it works with provided example.