Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cdata serialize with __eq metamethod #25

Open
sonoro1234 opened this issue Mar 25, 2021 · 6 comments
Open

cdata serialize with __eq metamethod #25

sonoro1234 opened this issue Mar 25, 2021 · 6 comments

Comments

@sonoro1234
Copy link

sonoro1234 commented Mar 25, 2021

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"

@gvx
Copy link
Owner

gvx commented Mar 25, 2021

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()).

@sonoro1234
Copy link
Author

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

@sonoro1234
Copy link
Author

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

@gvx
Copy link
Owner

gvx commented Mar 31, 2021

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.

@sonoro1234
Copy link
Author

Yes, it works with provided example.

@sonoro1234
Copy link
Author

Is this going to be added?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants