mirror of
https://github.com/gvx/bitser.git
synced 2024-11-11 01:44:21 +00:00
Add support for cdata
More testing needed
This commit is contained in:
parent
5a134b4fce
commit
caf972ca80
55
bitser.lua
55
bitser.lua
@ -1,5 +1,5 @@
|
||||
--[[
|
||||
Copyright (c) 2016, Robin Wellner
|
||||
Copyright (c) 2020, Jasmijn Wellner
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
@ -82,16 +82,18 @@ local function Buffer_write_byte(x)
|
||||
buf_pos = buf_pos + 1
|
||||
end
|
||||
|
||||
local function Buffer_write_raw(data, len)
|
||||
Buffer_reserve(len)
|
||||
ffi.copy(buf + buf_pos, data, len)
|
||||
buf_pos = buf_pos + len
|
||||
end
|
||||
|
||||
local function Buffer_write_string(s)
|
||||
Buffer_reserve(#s)
|
||||
ffi.copy(buf + buf_pos, s, #s)
|
||||
buf_pos = buf_pos + #s
|
||||
Buffer_write_raw(s, #s)
|
||||
end
|
||||
|
||||
local function Buffer_write_data(ct, len, ...)
|
||||
Buffer_reserve(len)
|
||||
ffi.copy(buf + buf_pos, ffi.new(ct, ...), len)
|
||||
buf_pos = buf_pos + len
|
||||
Buffer_write_raw(ffi.new(ct, ...), len)
|
||||
end
|
||||
|
||||
local function Buffer_ensure(numbytes)
|
||||
@ -114,12 +116,14 @@ local function Buffer_read_string(len)
|
||||
return x
|
||||
end
|
||||
|
||||
local function Buffer_read_data(ct, len)
|
||||
Buffer_ensure(len)
|
||||
local x = ffi.new(ct)
|
||||
ffi.copy(x, buf + buf_pos, len)
|
||||
local function Buffer_read_raw(data, len)
|
||||
ffi.copy(data, buf + buf_pos, len)
|
||||
buf_pos = buf_pos + len
|
||||
return x
|
||||
return data
|
||||
end
|
||||
|
||||
local function Buffer_read_data(ct, len)
|
||||
return Buffer_read_raw(ffi.new(ct), len)
|
||||
end
|
||||
|
||||
local resource_registry = {}
|
||||
@ -206,7 +210,23 @@ local function write_table(value, seen)
|
||||
end
|
||||
end
|
||||
|
||||
local types = {number = write_number, string = write_string, table = write_table, boolean = write_boolean, ["nil"] = write_nil}
|
||||
local function write_cdata(value, seen)
|
||||
local ty = ffi.typeof(value)
|
||||
if ty == value then
|
||||
-- ctype
|
||||
Buffer_write_byte(251)
|
||||
serialize_value(tostring(ty):sub(7, -2), seen)
|
||||
return
|
||||
end
|
||||
-- cdata
|
||||
Buffer_write_byte(252)
|
||||
serialize_value(ty, seen)
|
||||
local len = ffi.sizeof(value)
|
||||
write_number(len)
|
||||
Buffer_write_raw(ffi.typeof('$[1]', ty)(value), len)
|
||||
end
|
||||
|
||||
local types = {number = write_number, string = write_string, table = write_table, boolean = write_boolean, ["nil"] = write_nil, cdata = write_cdata}
|
||||
|
||||
serialize_value = function(value, seen)
|
||||
if seen[value] then
|
||||
@ -337,6 +357,15 @@ local function deserialize_value(seen)
|
||||
elseif t == 250 then
|
||||
--short int
|
||||
return Buffer_read_data("int16_t[1]", 2)[0]
|
||||
elseif t == 251 then
|
||||
--ctype
|
||||
return ffi.typeof(deserialize_value(seen))
|
||||
elseif t == 252 then
|
||||
local ctype = deserialize_value(seen)
|
||||
local len = deserialize_value(seen)
|
||||
local read_into = ffi.typeof('$[1]', ctype)()
|
||||
Buffer_read_raw(read_into, len)
|
||||
return ctype(read_into[0])
|
||||
else
|
||||
error("unsupported serialized type " .. t)
|
||||
end
|
||||
|
23
cases/cdata.lua
Normal file
23
cases/cdata.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local ffi = require("ffi")
|
||||
|
||||
ffi.cdef[[
|
||||
struct simple_struct {
|
||||
int a;
|
||||
int b;
|
||||
};
|
||||
|
||||
struct nested_struct {
|
||||
int a;
|
||||
struct simple_struct b;
|
||||
};
|
||||
]]
|
||||
|
||||
local bitser = require 'bitser'
|
||||
|
||||
local int_data = ffi.new('int', 5)
|
||||
|
||||
local struct_data = ffi.new('struct nested_struct', {10, {20, 30}})
|
||||
|
||||
local value = ffi.new('struct { int a; double b; }', 42, 1.25)
|
||||
|
||||
return {int_data, struct_data, value}, 1000, 3
|
16
main.lua
16
main.lua
@ -100,6 +100,12 @@ function love.draw()
|
||||
for i, case in ipairs(cases) do
|
||||
love.graphics.print(case, selected_case == i and 60 or 20, i * 20)
|
||||
end
|
||||
local i = 2
|
||||
love.graphics.print('serialisation libraries installed:', 200, 20)
|
||||
for sername in pairs(sers) do
|
||||
love.graphics.print(sername, 200, i * 20)
|
||||
i = i + 1
|
||||
end
|
||||
elseif state == 'calculate_results' then
|
||||
love.graphics.print("Running benchmark...", 20, 20)
|
||||
love.graphics.print("This may take a while", 20, 40)
|
||||
@ -111,6 +117,7 @@ function love.draw()
|
||||
resultname = "serialisation time in seconds"
|
||||
results_size = {}
|
||||
results_deser = {}
|
||||
errors = {}
|
||||
for sername, serializer in pairs(sers) do
|
||||
results_ser[sername] = math.huge
|
||||
results_deser[sername] = math.huge
|
||||
@ -126,7 +133,9 @@ function love.draw()
|
||||
end
|
||||
return os.clock() - t
|
||||
end)
|
||||
if success and diff < results_ser[sername] then
|
||||
if not success and not errors[sername] then
|
||||
errors[sername] = diff
|
||||
elseif success and diff < results_ser[sername] then
|
||||
results_ser[sername] = diff
|
||||
end
|
||||
if try == 1 then
|
||||
@ -145,7 +154,9 @@ function love.draw()
|
||||
end
|
||||
return os.clock() - t
|
||||
end)
|
||||
if success and diff < results_deser[sername] then
|
||||
if not success and not errors[sername] then
|
||||
errors[sername] = diff
|
||||
elseif success and diff < results_deser[sername] then
|
||||
results_deser[sername] = diff
|
||||
end
|
||||
end
|
||||
@ -171,6 +182,7 @@ function love.draw()
|
||||
love.graphics.setColor(220/256, 30/256, 0)
|
||||
love.graphics.rectangle('fill', 100, i * 20, 780 - 100, 18)
|
||||
love.graphics.setColor(40/256, 30/256, 0)
|
||||
love.graphics.print(errors[sername], 102, i * 20 + 2)
|
||||
else
|
||||
love.graphics.rectangle('fill', 100, i * 20, (780 - 100) * (result - results_min) / (results_max - results_min), 18)
|
||||
end
|
||||
|
@ -270,8 +270,6 @@ describe("bitser", function()
|
||||
assert.has_error(function() bitser.registerClass('Horse', {mane = 'majestic'}) end, "no deserializer given for unsupported class library")
|
||||
end)
|
||||
it("cannot deserialize values from unassigned type bytes", function()
|
||||
assert.has_error(function() bitser.loads("\251") end, "unsupported serialized type 251")
|
||||
assert.has_error(function() bitser.loads("\252") end, "unsupported serialized type 252")
|
||||
assert.has_error(function() bitser.loads("\253") end, "unsupported serialized type 253")
|
||||
assert.has_error(function() bitser.loads("\254") end, "unsupported serialized type 254")
|
||||
assert.has_error(function() bitser.loads("\255") end, "unsupported serialized type 255")
|
||||
@ -296,9 +294,25 @@ describe("bitser", function()
|
||||
bitser.loadData(ffi.new("uint8_t[4]", 195, 103, 118, 120), 4)
|
||||
test_serdeser("bitser")
|
||||
end)
|
||||
it("it can dump and load LÖVE files", function()
|
||||
it("can dump and load LÖVE files", function()
|
||||
local v = {value = "value"}
|
||||
bitser.dumpLoveFile("some_file_name", v)
|
||||
assert.are.same(v, bitser.loadLoveFile("some_file_name"))
|
||||
end)
|
||||
it("can read and write cdata", function()
|
||||
-- a simple value
|
||||
test_serdeser(ffi.new('double', 42.5))
|
||||
local value = ffi.new('struct some_struct { int a; double b; }', 42, 1.25)
|
||||
local type_of_struct = ffi.typeof(value)
|
||||
-- with a registered type
|
||||
bitser.register('struct_type', type_of_struct)
|
||||
test_serdeser(value)
|
||||
bitser.unregister('struct_type')
|
||||
-- with an unregistered type
|
||||
test_serdeser(value)
|
||||
end)
|
||||
it("cannot read from anonymous structs", function()
|
||||
local v = bitser.dumps(ffi.new('struct { int a; }'))
|
||||
assert.has_error(function() bitser.loads(v) end)
|
||||
end)
|
||||
end)
|
||||
|
Loading…
Reference in New Issue
Block a user