Fix bug #33 by changing the contract

"Pray I do not alter it any further."

On a serious note, I could not find a good reason to keep the old behaviour. It was niche at best, and class libraries tend to ultimately depend on `setmetatable` anyway, which just returns the original table, which has been mutated.

Now the return value of `deserializer` is simply ignored, and it is presumed the original table *is* the instance.
This commit is contained in:
Jasmijn Wellner 2024-12-31 10:36:41 +01:00
parent 5d11626898
commit c0b0e12dce
3 changed files with 11 additions and 15 deletions

View File

@ -198,8 +198,7 @@ to patch bitser. [See the list of supported class libraries](#supported-class-li
If not nil, the argument `classkey` should be a string such that
`rawget(obj, classkey) == class` for any `obj` whose type is `class`. This is done so that key is skipped for serialization.
If not nil, the argument `deserializer` should be a function such that `deserializer(obj, class)` returns a valid
instance of `class` with the properties of `obj`. `deserializer` is allowed to mutate `obj`.
If not nil, the argument `deserializer` should be a function such that `deserializer(obj, class)` mutates `obj` in a way that makes it a valid instance of `class`.
Returns the registered class as a convenience.

View File

@ -349,8 +349,7 @@ local function deserialize_value(seen)
return value
elseif t == 242 then
--instance
local instance_idx = reserve_seen(seen)
local instance = {}
local instance = add_to_seen({}, seen)
local classname = deserialize_value(seen)
local class = class_registry[classname]
local classkey = classkey_registry[classname]
@ -367,8 +366,7 @@ local function deserialize_value(seen)
if classkey then
instance[classkey] = class
end
instance = deserializer(instance, class)
seen[instance_idx] = instance
deserializer(instance, class)
return instance
elseif t == 243 then
--reference

View File

@ -328,30 +328,29 @@ describe("bitser", function()
it("is able to deserialize the same instance twice", function()
local class = {}
local instance = setmetatable({}, class)
local deserialize = function(_, _)
return instance
end
local deserialize = setmetatable
bitser.registerClass("class", class, nil, deserialize)
local loaded_instances = serdeser({instance, instance})
assert.are.equal(instance, loaded_instances[1], loaded_instances[2])
assert.are.equal(loaded_instances[1], loaded_instances[2])
assert.are.same(instance, loaded_instances[1])
bitser.unregisterClass("class")
end)
it("cannot deserialize an instance nested within itself", function()
it("is able to deserialize an instance nested within itself", function()
local class = {}
local instance = setmetatable({}, class)
local deserialize = function(_, _)
return instance
end
local deserialize = setmetatable
instance.myself = {instance}
bitser.registerClass("class", class, nil, deserialize)
assert.has_error(function() serdeser(instance) end, "trying to deserialize a value that has not yet been initialized")
local loaded_instance = serdeser(instance)
assert.are.equal(loaded_instance, loaded_instance.myself[1])
assert.are.same(instance, loaded_instance)
bitser.unregisterClass("class")
end)