Actually, going ahead and replacing the implementation

Thanks to git I can always roll back if this was a bad idea
This commit is contained in:
Robin Wellner 2016-02-23 12:44:46 +01:00
parent 529cd80c7a
commit 06d5b69b61
2 changed files with 141 additions and 537 deletions

View File

@ -22,79 +22,104 @@ local getmetatable = getmetatable
local setmetatable = setmetatable local setmetatable = setmetatable
local ffi = require("ffi") local ffi = require("ffi")
local buf_pos = 0
local buf_size = -1
local buf = nil
local writable_buf = nil
local writable_buf_size = nil
local function Buffer_prereserve(min_size)
if buf_size < min_size then
buf_size = min_size
buf = ffi.new("uint8_t[?]", buf_size)
end
end
local function Buffer_makeBuffer(size)
if writable_buf then
buf = writable_buf
buf_size = writable_buf_size
writable_buf = nil
writable_buf_size = nil
end
buf_pos = 0
Buffer_prereserve(size)
end
local function Buffer_newWriter(size) local function Buffer_newWriter(size)
size = size or 4096 Buffer_makeBuffer(size or 0)
return {size = size, pos = 0, buf = ffi.new("uint8_t[?]", size)}
end end
local function Buffer_newReader(str) local function Buffer_newReader(str)
local buf = ffi.new("uint8_t[?]", #str) Buffer_makeBuffer(#str)
ffi.copy(buf, str, #str) ffi.copy(buf, str, #str)
return {size = #str, pos = 0, buf = buf}
end end
local function Buffer_newDataReader(data, size) local function Buffer_newDataReader(data, size)
return {size = size, pos = 0, buf = ffi.cast("uint8_t*", data)} writable_buf = buf
writable_buf_size = buf_size
buf_pos = 0
buf_size = size
buf = ffi.cast("uint8_t*", data)
end end
local function Buffer_reserve(self, additional_size) local function Buffer_reserve(additional_size)
while self.pos + additional_size > self.size do while buf_pos + additional_size > buf_size do
self.size = self.size * 2 buf_size = buf_size * 2
local oldbuf = self.buf local oldbuf = buf
self.buf = ffi.new("uint8_t[?]", self.size) buf = ffi.new("uint8_t[?]", buf_size)
ffi.copy(self.buf, oldbuf, self.pos) ffi.copy(buf, oldbuf, buf_pos)
end end
end end
local function Buffer_write_byte(self, x) local function Buffer_write_byte(x)
Buffer_reserve(self, 1) Buffer_reserve(1)
self.buf[self.pos] = x buf[buf_pos] = x
self.pos = self.pos + 1 buf_pos = buf_pos + 1
end end
local function Buffer_write_string(self, s) local function Buffer_write_string(s)
Buffer_reserve(self, #s) Buffer_reserve(#s)
ffi.copy(self.buf + self.pos, s, #s) ffi.copy(buf + buf_pos, s, #s)
self.pos = self.pos + #s buf_pos = buf_pos + #s
end end
local function Buffer_write_data(self, ct, len, ...) local function Buffer_write_data(ct, len, ...)
Buffer_reserve(self, len) Buffer_reserve(len)
ffi.copy(self.buf + self.pos, ffi.new(ct, ...), len) ffi.copy(buf + buf_pos, ffi.new(ct, ...), len)
self.pos = self.pos + len buf_pos = buf_pos + len
end end
local function Buffer_get(self) local function Buffer_get()
return self.buf, self.pos return buf, buf_pos
end end
local function Buffer_ensure(self, numbytes) local function Buffer_ensure(numbytes)
if self.pos + numbytes > self.size then if buf_pos + numbytes > buf_size then
error("malformed serialized data") error("malformed serialized data")
end end
end end
local function Buffer_read_byte(self) local function Buffer_read_byte()
Buffer_ensure(self, 1) Buffer_ensure(1)
local x = self.buf[self.pos] local x = buf[buf_pos]
self.pos = self.pos + 1 buf_pos = buf_pos + 1
return x return x
end end
local function Buffer_read_string(self, len) local function Buffer_read_string(len)
Buffer_ensure(self, len) Buffer_ensure(len)
local pos = self.pos local x = ffi.string(buf + buf_pos, len)
self.pos = pos + len buf_pos = buf_pos + len
return ffi.string(self.buf + pos, len) return x
end end
local function Buffer_read_data(self, ct, len) local function Buffer_read_data(ct, len)
Buffer_ensure(self, len) Buffer_ensure(len)
local t = ffi.new(ct) local x = ffi.new(ct)
ffi.copy(t, self.buf + self.pos, len) ffi.copy(x, buf + buf_pos, len)
self.pos = self.pos + len buf_pos = buf_pos + len
return t return x
end end
local resource_registry = {} local resource_registry = {}
@ -106,48 +131,48 @@ local class_deserialize_registry = {}
local serialize_value local serialize_value
local function write_number(value, buffer, _) local function write_number(value, _)
if floor(value) == value and value >= -2147483648 and value <= 2147483647 then if floor(value) == value and value >= -2147483648 and value <= 2147483647 then
if value >= -27 and value <= 100 then if value >= -27 and value <= 100 then
--small int --small int
Buffer_write_byte(buffer, value + 27) Buffer_write_byte(value + 27)
elseif value >= -32768 and value <= 32767 then elseif value >= -32768 and value <= 32767 then
--short int --short int
Buffer_write_byte(buffer, 250) Buffer_write_byte(250)
Buffer_write_data(buffer, "int16_t[1]", 2, value) Buffer_write_data("int16_t[1]", 2, value)
else else
--long int --long int
Buffer_write_byte(buffer, 245) Buffer_write_byte(245)
Buffer_write_data(buffer, "int32_t[1]", 4, value) Buffer_write_data("int32_t[1]", 4, value)
end end
else else
--double --double
Buffer_write_byte(buffer, 246) Buffer_write_byte(246)
Buffer_write_data(buffer, "double[1]", 8, value) Buffer_write_data("double[1]", 8, value)
end end
end end
local function write_string(value, buffer, seen) local function write_string(value, seen)
if #value < 32 then if #value < 32 then
--short string --short string
Buffer_write_byte(buffer, 192 + #value) Buffer_write_byte(192 + #value)
else else
--long string --long string
Buffer_write_byte(buffer, 244) Buffer_write_byte(244)
write_number(#value, buffer, seen) write_number(#value, seen)
end end
Buffer_write_string(buffer, value) Buffer_write_string(value)
end end
local function write_nil(_, buffer, _) local function write_nil(_, _)
Buffer_write_byte(buffer, 247) Buffer_write_byte(247)
end end
local function write_boolean(value, buffer, _) local function write_boolean(value, _)
Buffer_write_byte(buffer, value and 249 or 248) Buffer_write_byte(value and 249 or 248)
end end
local function write_table(value, buffer, seen) local function write_table(value, seen)
local classkey local classkey
local class = (class_name_registry[value.class] -- MiddleClass local class = (class_name_registry[value.class] -- MiddleClass
or class_name_registry[value.__baseclass] -- SECL or class_name_registry[value.__baseclass] -- SECL
@ -155,15 +180,15 @@ local function write_table(value, buffer, seen)
or class_name_registry[value.__class__]) -- Slither or class_name_registry[value.__class__]) -- Slither
if class then if class then
classkey = classkey_registry[class] classkey = classkey_registry[class]
Buffer_write_byte(buffer, 242) Buffer_write_byte(242)
write_string(class, buffer) write_string(class)
else else
Buffer_write_byte(buffer, 240) Buffer_write_byte(240)
end end
local len = #value local len = #value
write_number(len, buffer, seen) write_number(len, seen)
for i = 1, len do for i = 1, len do
serialize_value(value[i], buffer, seen) serialize_value(value[i], seen)
end end
local klen = 0 local klen = 0
for k in pairs(value) do for k in pairs(value) do
@ -171,27 +196,27 @@ local function write_table(value, buffer, seen)
klen = klen + 1 klen = klen + 1
end end
end end
write_number(klen, buffer, seen) write_number(klen, seen)
for k, v in pairs(value) do for k, v in pairs(value) do
if (type(k) ~= 'number' or floor(k) ~= k or k > len or k < 1) and k ~= classkey then if (type(k) ~= 'number' or floor(k) ~= k or k > len or k < 1) and k ~= classkey then
serialize_value(k, buffer, seen) serialize_value(k, seen)
serialize_value(v, buffer, seen) serialize_value(v, seen)
end end
end end
end end
local types = {number = write_number, string = write_string, table = write_table, boolean = write_boolean, ["nil"] = write_nil} local types = {number = write_number, string = write_string, table = write_table, boolean = write_boolean, ["nil"] = write_nil}
serialize_value = function(value, buffer, seen) serialize_value = function(value, seen)
if seen[value] then if seen[value] then
local ref = seen[value] local ref = seen[value]
if ref < 64 then if ref < 64 then
--small reference --small reference
Buffer_write_byte(buffer, 128 + ref) Buffer_write_byte(128 + ref)
else else
--long reference --long reference
Buffer_write_byte(buffer, 243) Buffer_write_byte(243)
write_number(ref, buffer, seen) write_number(ref, seen)
end end
return return
end end
@ -204,25 +229,25 @@ serialize_value = function(value, buffer, seen)
local name = resource_name_registry[value] local name = resource_name_registry[value]
if #name < 16 then if #name < 16 then
--small resource --small resource
Buffer_write_byte(buffer, 224 + #name) Buffer_write_byte(224 + #name)
Buffer_write_string(buffer, name) Buffer_write_string(name)
else else
--long resource --long resource
Buffer_write_byte(buffer, 241) Buffer_write_byte(241)
write_string(name, buffer, seen) write_string(name, seen)
end end
return return
end end
(types[t] or (types[t] or
error("cannot serialize type " .. t) error("cannot serialize type " .. t)
)(value, buffer, seen) )(value, seen)
end end
local function serialize(value) local function serialize(value)
local buffer = Buffer_newWriter() Buffer_newWriter()
local seen = {len = 0} local seen = {len = 0}
serialize_value(value, buffer, seen) serialize_value(value, seen)
return Buffer_get(buffer) return Buffer_get()
end end
local function add_to_seen(value, seen) local function add_to_seen(value, seen)
@ -235,8 +260,8 @@ local function reserve_seen(seen)
return #seen return #seen
end end
local function deserialize_value(buffer, seen) local function deserialize_value(seen)
local t = Buffer_read_byte(buffer) local t = Buffer_read_byte()
if t < 128 then if t < 128 then
--small int --small int
return t - 27 return t - 27
@ -245,44 +270,44 @@ local function deserialize_value(buffer, seen)
return seen[t - 127] return seen[t - 127]
elseif t < 224 then elseif t < 224 then
--small string --small string
return add_to_seen(Buffer_read_string(buffer, t - 192), seen) return add_to_seen(Buffer_read_string(t - 192), seen)
elseif t < 240 then elseif t < 240 then
--small resource --small resource
return add_to_seen(resource_registry[Buffer_read_string(buffer, t - 224)], seen) return add_to_seen(resource_registry[Buffer_read_string(t - 224)], seen)
elseif t == 240 then elseif t == 240 then
--table --table
local v = add_to_seen({}, seen) local v = add_to_seen({}, seen)
local len = deserialize_value(buffer, seen) local len = deserialize_value(seen)
for i = 1, len do for i = 1, len do
v[i] = deserialize_value(buffer, seen) v[i] = deserialize_value(seen)
end end
len = deserialize_value(buffer, seen) len = deserialize_value(seen)
for _ = 1, len do for _ = 1, len do
local key = deserialize_value(buffer, seen) local key = deserialize_value(seen)
v[key] = deserialize_value(buffer, seen) v[key] = deserialize_value(seen)
end end
return v return v
elseif t == 241 then elseif t == 241 then
--long resource --long resource
local idx = reserve_seen(seen) local idx = reserve_seen(seen)
local value = resource_registry[deserialize_value(buffer, seen)] local value = resource_registry[deserialize_value(seen)]
seen[idx] = value seen[idx] = value
return value return value
elseif t == 242 then elseif t == 242 then
--instance --instance
local instance = add_to_seen({}, seen) local instance = add_to_seen({}, seen)
local classname = deserialize_value(buffer, seen) local classname = deserialize_value(seen)
local class = class_registry[classname] local class = class_registry[classname]
local classkey = classkey_registry[classname] local classkey = classkey_registry[classname]
local deserializer = class_deserialize_registry[classname] local deserializer = class_deserialize_registry[classname]
local len = deserialize_value(buffer, seen) local len = deserialize_value(seen)
for i = 1, len do for i = 1, len do
instance[i] = deserialize_value(buffer, seen) instance[i] = deserialize_value(seen)
end end
len = deserialize_value(buffer, seen) len = deserialize_value(seen)
for _ = 1, len do for _ = 1, len do
local key = deserialize_value(buffer, seen) local key = deserialize_value(seen)
instance[key] = deserialize_value(buffer, seen) instance[key] = deserialize_value(seen)
end end
if classkey then if classkey then
instance[classkey] = class instance[classkey] = class
@ -290,16 +315,16 @@ local function deserialize_value(buffer, seen)
return deserializer(instance, class) return deserializer(instance, class)
elseif t == 243 then elseif t == 243 then
--reference --reference
return seen[deserialize_value(buffer, seen) + 1] return seen[deserialize_value(seen) + 1]
elseif t == 244 then elseif t == 244 then
--long string --long string
return add_to_seen(Buffer_read_string(buffer, deserialize_value(buffer, seen)), seen) return add_to_seen(Buffer_read_string(deserialize_value(seen)), seen)
elseif t == 245 then elseif t == 245 then
--long int --long int
return Buffer_read_data(buffer, "int32_t[1]", 4)[0] return Buffer_read_data("int32_t[1]", 4)[0]
elseif t == 246 then elseif t == 246 then
--double --double
return Buffer_read_data(buffer, "double[1]", 8)[0] return Buffer_read_data("double[1]", 8)[0]
elseif t == 247 then elseif t == 247 then
--nil --nil
return nil return nil
@ -311,17 +336,12 @@ local function deserialize_value(buffer, seen)
return true return true
elseif t == 250 then elseif t == 250 then
--short int --short int
return Buffer_read_data(buffer, "int16_t[1]", 2)[0] return Buffer_read_data("int16_t[1]", 2)[0]
else else
error("unsupported serialized type " .. t) error("unsupported serialized type " .. t)
end end
end end
local function deserialize(buffer)
local seen = {}
return deserialize_value(buffer, seen)
end
local function deserialize_MiddleClass(instance, class) local function deserialize_MiddleClass(instance, class)
return setmetatable(instance, class.__instanceDict) return setmetatable(instance, class.__instanceDict)
end end
@ -339,9 +359,11 @@ end
return {dumps = function(value) return {dumps = function(value)
return ffi.string(serialize(value)) return ffi.string(serialize(value))
end, loadData = function(data, size) end, loadData = function(data, size)
return deserialize(Buffer_newDataReader(data, size)) Buffer_newDataReader(data, size)
return deserialize_value({})
end, loads = function(str) end, loads = function(str)
return deserialize(Buffer_newReader(str)) Buffer_newReader(str)
return deserialize_value({})
end, register = function(name, resource) end, register = function(name, resource)
assert(not resource_registry[name], name .. " already registered") assert(not resource_registry[name], name .. " already registered")
resource_registry[name] = resource resource_registry[name] = resource
@ -393,4 +415,4 @@ end, unregisterClass = function(name)
classkey_registry[name] = nil classkey_registry[name] = nil
class_deserialize_registry[name] = nil class_deserialize_registry[name] = nil
class_registry[name] = nil class_registry[name] = nil
end} end, reserve_buffer = Buffer_prereserve}

View File

@ -1,418 +0,0 @@
--[[
Copyright (c) 2016, Robin 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
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
]]
local floor = math.floor
local pairs = pairs
local type = type
local insert = table.insert
local getmetatable = getmetatable
local setmetatable = setmetatable
local ffi = require("ffi")
local buf_pos = 0
local buf_size = -1
local buf = nil
local writable_buf = nil
local writable_buf_size = nil
local function Buffer_prereserve(min_size)
if buf_size < min_size then
buf_size = min_size
buf = ffi.new("uint8_t[?]", buf_size)
end
end
local function Buffer_makeBuffer(size)
if writable_buf then
buf = writable_buf
buf_size = writable_buf_size
writable_buf = nil
writable_buf_size = nil
end
buf_pos = 0
Buffer_prereserve(size)
end
local function Buffer_newWriter(size)
Buffer_makeBuffer(size or 0)
end
local function Buffer_newReader(str)
Buffer_makeBuffer(#str)
ffi.copy(buf, str, #str)
end
local function Buffer_newDataReader(data, size)
writable_buf = buf
writable_buf_size = buf_size
buf_pos = 0
buf_size = size
buf = ffi.cast("uint8_t*", data)
end
local function Buffer_reserve(additional_size)
while buf_pos + additional_size > buf_size do
buf_size = buf_size * 2
local oldbuf = buf
buf = ffi.new("uint8_t[?]", buf_size)
ffi.copy(buf, oldbuf, buf_pos)
end
end
local function Buffer_write_byte(x)
Buffer_reserve(1)
buf[buf_pos] = x
buf_pos = buf_pos + 1
end
local function Buffer_write_string(s)
Buffer_reserve(#s)
ffi.copy(buf + buf_pos, s, #s)
buf_pos = buf_pos + #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
end
local function Buffer_get()
return buf, buf_pos
end
local function Buffer_ensure(numbytes)
if buf_pos + numbytes > buf_size then
error("malformed serialized data")
end
end
local function Buffer_read_byte()
Buffer_ensure(1)
local x = buf[buf_pos]
buf_pos = buf_pos + 1
return x
end
local function Buffer_read_string(len)
Buffer_ensure(len)
local x = ffi.string(buf + buf_pos, len)
buf_pos = buf_pos + 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)
buf_pos = buf_pos + len
return x
end
local resource_registry = {}
local resource_name_registry = {}
local class_registry = {}
local class_name_registry = {}
local classkey_registry = {}
local class_deserialize_registry = {}
local serialize_value
local function write_number(value, _)
if floor(value) == value and value >= -2147483648 and value <= 2147483647 then
if value >= -27 and value <= 100 then
--small int
Buffer_write_byte(value + 27)
elseif value >= -32768 and value <= 32767 then
--short int
Buffer_write_byte(250)
Buffer_write_data("int16_t[1]", 2, value)
else
--long int
Buffer_write_byte(245)
Buffer_write_data("int32_t[1]", 4, value)
end
else
--double
Buffer_write_byte(246)
Buffer_write_data("double[1]", 8, value)
end
end
local function write_string(value, seen)
if #value < 32 then
--short string
Buffer_write_byte(192 + #value)
else
--long string
Buffer_write_byte(244)
write_number(#value, seen)
end
Buffer_write_string(value)
end
local function write_nil(_, _)
Buffer_write_byte(247)
end
local function write_boolean(value, _)
Buffer_write_byte(value and 249 or 248)
end
local function write_table(value, seen)
local classkey
local class = (class_name_registry[value.class] -- MiddleClass
or class_name_registry[value.__baseclass] -- SECL
or class_name_registry[getmetatable(value)] -- hump.class
or class_name_registry[value.__class__]) -- Slither
if class then
classkey = classkey_registry[class]
Buffer_write_byte(242)
write_string(class)
else
Buffer_write_byte(240)
end
local len = #value
write_number(len, seen)
for i = 1, len do
serialize_value(value[i], seen)
end
local klen = 0
for k in pairs(value) do
if (type(k) ~= 'number' or floor(k) ~= k or k > len or k < 1) and k ~= classkey then
klen = klen + 1
end
end
write_number(klen, seen)
for k, v in pairs(value) do
if (type(k) ~= 'number' or floor(k) ~= k or k > len or k < 1) and k ~= classkey then
serialize_value(k, seen)
serialize_value(v, seen)
end
end
end
local types = {number = write_number, string = write_string, table = write_table, boolean = write_boolean, ["nil"] = write_nil}
serialize_value = function(value, seen)
if seen[value] then
local ref = seen[value]
if ref < 64 then
--small reference
Buffer_write_byte(128 + ref)
else
--long reference
Buffer_write_byte(243)
write_number(ref, seen)
end
return
end
local t = type(value)
if t ~= 'number' and t ~= 'boolean' and t ~= 'nil' then
seen[value] = seen.len
seen.len = seen.len + 1
end
if resource_name_registry[value] then
local name = resource_name_registry[value]
if #name < 16 then
--small resource
Buffer_write_byte(224 + #name)
Buffer_write_string(name)
else
--long resource
Buffer_write_byte(241)
write_string(name, seen)
end
return
end
(types[t] or
error("cannot serialize type " .. t)
)(value, seen)
end
local function serialize(value)
Buffer_newWriter()
local seen = {len = 0}
serialize_value(value, seen)
return Buffer_get()
end
local function add_to_seen(value, seen)
insert(seen, value)
return value
end
local function reserve_seen(seen)
insert(seen, 42)
return #seen
end
local function deserialize_value(seen)
local t = Buffer_read_byte()
if t < 128 then
--small int
return t - 27
elseif t < 192 then
--small reference
return seen[t - 127]
elseif t < 224 then
--small string
return add_to_seen(Buffer_read_string(t - 192), seen)
elseif t < 240 then
--small resource
return add_to_seen(resource_registry[Buffer_read_string(t - 224)], seen)
elseif t == 240 then
--table
local v = add_to_seen({}, seen)
local len = deserialize_value(seen)
for i = 1, len do
v[i] = deserialize_value(seen)
end
len = deserialize_value(seen)
for _ = 1, len do
local key = deserialize_value(seen)
v[key] = deserialize_value(seen)
end
return v
elseif t == 241 then
--long resource
local idx = reserve_seen(seen)
local value = resource_registry[deserialize_value(seen)]
seen[idx] = value
return value
elseif t == 242 then
--instance
local instance = add_to_seen({}, seen)
local classname = deserialize_value(seen)
local class = class_registry[classname]
local classkey = classkey_registry[classname]
local deserializer = class_deserialize_registry[classname]
local len = deserialize_value(seen)
for i = 1, len do
instance[i] = deserialize_value(seen)
end
len = deserialize_value(seen)
for _ = 1, len do
local key = deserialize_value(seen)
instance[key] = deserialize_value(seen)
end
if classkey then
instance[classkey] = class
end
return deserializer(instance, class)
elseif t == 243 then
--reference
return seen[deserialize_value(seen) + 1]
elseif t == 244 then
--long string
return add_to_seen(Buffer_read_string(deserialize_value(seen)), seen)
elseif t == 245 then
--long int
return Buffer_read_data("int32_t[1]", 4)[0]
elseif t == 246 then
--double
return Buffer_read_data("double[1]", 8)[0]
elseif t == 247 then
--nil
return nil
elseif t == 248 then
--false
return false
elseif t == 249 then
--true
return true
elseif t == 250 then
--short int
return Buffer_read_data("int16_t[1]", 2)[0]
else
error("unsupported serialized type " .. t)
end
end
local function deserialize_MiddleClass(instance, class)
return setmetatable(instance, class.__instanceDict)
end
local function deserialize_SECL(instance, class)
return setmetatable(instance, getmetatable(class))
end
local deserialize_humpclass = setmetatable
local function deserialize_Slither(instance, class)
return getmetatable(class).allocate(instance)
end
return {dumps = function(value)
return ffi.string(serialize(value))
end, loadData = function(data, size)
Buffer_newDataReader(data, size)
return deserialize_value({})
end, loads = function(str)
Buffer_newReader(str)
return deserialize_value({})
end, register = function(name, resource)
assert(not resource_registry[name], name .. " already registered")
resource_registry[name] = resource
resource_name_registry[resource] = name
return resource
end, unregister = function(name)
resource_name_registry[resource_registry[name]] = nil
resource_registry[name] = nil
end, registerClass = function(name, class, classkey, deserializer)
if not class then
class = name
name = class.__name__ or class.name
end
if not classkey then
if class.__instanceDict then
-- assume MiddleClass
classkey = 'class'
elseif class.__baseclass then
-- assume SECL
classkey = '__baseclass'
end
-- assume hump.class, Slither, or something else that doesn't store the
-- class directly on the instance
end
if not deserializer then
if class.__instanceDict then
-- assume MiddleClass
deserializer = deserialize_MiddleClass
elseif class.__baseclass then
-- assume SECL
deserializer = deserialize_SECL
elseif class.__index == class then
-- assume hump.class
deserializer = deserialize_humpclass
elseif class.__name__ then
-- assume Slither
deserializer = deserialize_Slither
else
error("no deserializer given for unsupported class library")
end
end
class_registry[name] = class
classkey_registry[name] = classkey
class_deserialize_registry[name] = deserializer
class_name_registry[class] = name
return class
end, unregisterClass = function(name)
class_name_registry[class_registry[name]] = nil
classkey_registry[name] = nil
class_deserialize_registry[name] = nil
class_registry[name] = nil
end, reserve_buffer = Buffer_prereserve}