Skip to content

Instantly share code, notes, and snippets.

@bigbes
Created April 22, 2016 16:44
Show Gist options
  • Save bigbes/c1b5b0fa7146bc2c0eed79275f6b3e11 to your computer and use it in GitHub Desktop.
Save bigbes/c1b5b0fa7146bc2c0eed79275f6b3e11 to your computer and use it in GitHub Desktop.
local ffi = require('ffi')
local buffer = require('buffer')
local builtin = ffi.C
ffi.cdef[[
char *mp_encode_nil (char *data);
void mp_decode_nil (const char **data);
bool mp_decode_bool (const char **data);
char *mp_encode_bool (char *data, bool val);
char *mp_encode_int (const char *data, int64_t val);
char *mp_encode_uint (const char *data, uint64_t val);
uint32_t mp_sizeof_int (int64_t val);
uint32_t mp_sizeof_uint (uint64_t val);
int64_t mp_decode_int (const char **data);
uint64_t mp_decode_uint (const char **data);
char *mp_encode_str (char *data, const char *str, uint32_t len);
char *mp_encode_strl (char *data, uint32_t len);
uint32_t mp_sizeof_str (uint32_t len);
uint32_t mp_sizeof_strl (uint32_t len);
const char *mp_decode_str (char **data, uint32_t *len);
uint32_t mp_decode_strl (char **data);
char *mp_encode_float (char *data, float num);
char *mp_encode_double (char *data, double num);
float mp_decode_float (const char **data);
double mp_decode_double (const char **data);
char *mp_encode_map (char *data, uint32_t size)
char *mp_encode_array (char *data, uint32_t size);
uint32_t mp_sizeof_map (uint32_t size)
uint32_t mp_sizeof_array (uint32_t size)
uint32_t mp_decode_map (const char **data)
uint32_t mp_decode_array (const char **data);
]]
local type_to_state = {
[[nil]] = 2,
[[boolean]] = 3,
-- it must forward to appropriate type:
-- * double -> 8
-- OR -> 9
-- * - number < 0 -> 10
-- OR
-- - number >= 0 -> 11
[[number]] = 4,
[[string]] = 5,
-- it must forward to appropriate type:
-- * hash -> 11
-- OR
-- * array -> 12
[[table]] = 6,
-- it must execute needed callback from encode_ext_data
[[cdata]] = 7,
}
local encode_ext_cdata = {}
-- Set trigger that called when encoding cdata
local function on_encode(ctype_or_udataname, callback)
if type(ctype_or_udataname) ~= "cdata" or type(callback) ~= "function" then
error("Usage: on_encode(ffi.typeof('mytype'), function(buf, obj)")
end
local ctypeid = tonumber(ffi.typeof(ctype_or_udataname))
local prev = encode_ext_cdata[ctypeid]
encode_ext_cdata[ctypeid] = callback
return prev
end
--[[
on_encode(ffi.typeof('uint8_t'), encode_int)
on_encode(ffi.typeof('uint16_t'), encode_int)
on_encode(ffi.typeof('uint32_t'), encode_int)
on_encode(ffi.typeof('uint64_t'), encode_int)
on_encode(ffi.typeof('int8_t'), encode_int)
on_encode(ffi.typeof('int16_t'), encode_int)
on_encode(ffi.typeof('int32_t'), encode_int)
on_encode(ffi.typeof('int64_t'), encode_int)
on_encode(ffi.typeof('char'), encode_int)
on_encode(ffi.typeof('const char'), encode_int)
on_encode(ffi.typeof('unsigned char'), encode_int)
on_encode(ffi.typeof('const unsigned char'), encode_int)
on_encode(ffi.typeof('bool'), encode_bool_cdata)
on_encode(ffi.typeof('float'), encode_float)
on_encode(ffi.typeof('double'), encode_double)
]]--
local function encode_r_jit(buf, obj)
local dyn = require('table.new')(MAXNESTING, 0)
local state = 1
local depth = 1
dyn[depth] = obj
for i = 1, 1000000000, 1 do
if state == 1 then
state = type_to_state[type(dyn[depth])]
elseif state == 2 then
local p = buf:alloc(1)
builtin.mp_encode_nil(p)
---- OR
-- encode_fix(bug, 0xc0, 0)
---- OR
-- local p = buf:alloc(1)
-- p[0] = 0xc0
elseif state == 3 then
local p = buf:alloc(1)
builtin.mp_encode_bool(p, val and 1 or 0)
---- OR
-- encode_fix(buf, 0xc2, val and 1 or 0)
elseif state == 4 then
state = (obj % 1 == 0 and obj > -1e63 and obj < 1e64) and 8 or 9
elseif state == 5 then
local ssz = #obj
local bsz = builtin.mp_sizeof_str(ssz)
local p = buf:alloc(bsz)
builtin.mp_encode_str(p, obj, ssz)
elseif state == 7 then
local
local
elseif state == 8 then
local
elseif state == 9 then
state = (obj >= 0) and 10 or 11
elseif state == 10 then
local sz = builtin.mp_sizeof_int(obj)
local p = buf:alloc(sz)
builtin.mp_encode_int(p, obj)
elseif state == 11 then
local sz = builtin.mp_sizeof_uint(obj)
local p = buf:alloc(sz)
builtin.mp_encode_uint(p, obj)
end
end
end
return {
encode = encode_r_jit
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment