Add an extension for #24

This is only a simplified system. A full implementation would need to add support for nested keys, and also support the same set of class libraries that bitser does.
This commit is contained in:
Jasmijn Wellner 2024-12-29 19:33:44 +01:00
parent 3d259bb196
commit 71d2d7d73f
2 changed files with 93 additions and 0 deletions

View File

@ -0,0 +1,55 @@
-- this implements a simplified form of binser templates (without nested keys)
local templates_by_identity = {} -- template -> name
local templates_by_name = {}
local class_by_templatename = {}
local function bitser_match(value)
return value._template ~= nil and templates_by_identity[value._template]
end
local function bitser_dump(value)
local templatename = templates_by_identity[value._template]
local template = templates_by_name[templatename]
local output = {templatename}
local extras = {}
for k, v in pairs(value) do
extras[k] = v
end
for i, key in ipairs(template) do
output[i + 1] = extras[key]
extras[key] = nil
end
output[#output + 1] = extras
return output
end
local function bitser_load(value)
local templatename = value[1]
local obj = {}
local template = templates_by_name[templatename]
for i, keyname in ipairs(template) do
obj[keyname] = value[i + 1]
end
for k, v in pairs(value[#value]) do
obj[k] = v
end
return setmetatable(obj, class_by_templatename[templatename])
end
local function register(class, name)
name = name or class.name
templates_by_identity[class._template] = name
templates_by_name[name] = class._template ---parse_template(class._template)
class_by_templatename[name] = class
return class
end
return {
registerClass = register,
["bitser-type"] = 'table',
["bitser-match"] = bitser_match,
["bitser-dump"] = bitser_dump,
["bitser-load"] = bitser_load,
}

38
examples/templates.lua Normal file
View File

@ -0,0 +1,38 @@
-- how to use the extension API to implement templates ala
-- https://github.com/bakpakin/binser#templates
local bitser = require 'bitser'
local bitser_templates = require 'examples.bitser-templates'
bitser.registerExtension('templates', bitser_templates)
local template = {
"name", "age", "salary", "email", "nested"
--nested = {'more', 'nested', 'keys'}
}
local Employee_MT = {
__name__ = 'Employee_MT',
name = "Employee",
_template = template
}
Employee_MT.__index = Employee_MT
local joe = setmetatable({
name = "Joe",
age = 11,
salary = "$1,000,000",
email = "joe@example.com",
nested = {
more = "blah",
nested = "FUBAR",
keys = "lost"
}
}, Employee_MT)
bitser.registerClass(Employee_MT)
print('without templates:', #bitser.dumps(joe))
bitser.unregisterClass('Employee_MT')
bitser_templates.registerClass(Employee_MT)
print('with templates:', #bitser.dumps(joe))