packages feed

pbc4hs 0.1.0.0 → 0.1.1.0

raw patch · 2 files changed

+576/−2 lines, 2 filesdep +string-qq

Dependencies added: string-qq

Files

pbc4hs.cabal view
@@ -1,5 +1,5 @@ name:                pbc4hs-version:             0.1.0.0+version:             0.1.1.0 synopsis:            pbc for HsLua description:         pbc wrapper for HsLua license:             BSD3@@ -9,6 +9,7 @@ category:            System build-type:          Simple cabal-version:       >=1.10+homepage:            https://github.com/DavidFeng/pbc4hs  extra-source-files:  cbits/alloc.h                      cbits/array.h@@ -22,10 +23,15 @@                      cbits/stringpool.h                      cbits/varint.h +source-repository head+  type:                 git+  location:             https://github.com/osa1/hslua.git+ library   exposed-modules:     Scripting.Lua.Pbc   other-extensions:    ForeignFunctionInterface   build-depends:       base >=4.6 && <4.7, hslua >=0.3 && <0.4+                       , string-qq >= 0.0.2   hs-source-dirs:      src   default-language:    Haskell2010 
src/Scripting/Lua/Pbc.hs view
@@ -1,16 +1,584 @@ {-# LANGUAGE ForeignFunctionInterface #-}+{-# LANGUAGE QuasiQuotes              #-}  -- | pbc library wrapper, useful when sometimes require from dylib doesn't -- work well module Scripting.Lua.Pbc ( -- ** functions                            openPbc+                         , openLuaPbc                          ) where  import Scripting.Lua+import Data.String.QQ  foreign import ccall "luaopen_protobuf_c" c_luaopen_pbc :: LuaState -> IO () --- | open pbc Lua library+-- | open pbc Lua C binding library openPbc :: LuaState -> IO () openPbc = c_luaopen_pbc +-- | open pbc Lua library+openLuaPbc :: LuaState -> IO ()+openLuaPbc l = do+    c_luaopen_pbc l+    loadstring l protobuf_lua "protobuf.lua"+    call l 0 0++protobuf_lua :: String+protobuf_lua = [s|+local c = require "protobuf.c"++local setmetatable = setmetatable+local type = type+local table = table+local assert = assert+local pairs = pairs+local ipairs = ipairs+local string = string+local print = print+local io = io+local tinsert = table.insert+local rawget = rawget++module "protobuf"++local _pattern_cache = {}++-- skynet clear+local P = c._env_new()+local GC = c._gc(P)++function lasterror()+    return c._last_error(P)+end++local decode_type_cache = {}+local _R_meta = {}++function _R_meta:__index(key)+    local v = decode_type_cache[self._CType][key](self, key)+    self[key] = v+    return v+end++local _reader = {}++function _reader:int(key)+    return c._rmessage_integer(self._CObj , key , 0)+end++function _reader:real(key)+    return c._rmessage_real(self._CObj , key , 0)+end++function _reader:string(key)+    return c._rmessage_string(self._CObj , key , 0)+end++function _reader:bool(key)+    return c._rmessage_integer(self._CObj , key , 0) ~= 0+end++function _reader:message(key, message_type)+    local rmessage = c._rmessage_message(self._CObj , key , 0)+    if rmessage then+        local v = {+            _CObj = rmessage,+            _CType = message_type,+            _Parent = self,+        }+        return setmetatable( v , _R_meta )+    end+end++function _reader:int32(key)+    return c._rmessage_int32(self._CObj , key , 0)+end++function _reader:int64(key)+    return c._rmessage_int64(self._CObj , key , 0)+end++function _reader:int52(key)+    return c._rmessage_int52(self._CObj , key , 0)+end++function _reader:uint52(key)+    return c._rmessage_uint52(self._CObj , key , 0)+end++function _reader:int_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_integer(cobj , key , i))+    end+    return ret+end++function _reader:real_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_real(cobj , key , i))+    end+    return ret+end++function _reader:string_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_string(cobj , key , i))+    end+    return ret+end++function _reader:bool_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_integer(cobj , key , i) ~= 0)+    end+    return ret+end++function _reader:message_repeated(key, message_type)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        local m = {+            _CObj = c._rmessage_message(cobj , key , i),+            _CType = message_type,+            _Parent = self,+        }+        tinsert(ret, setmetatable( m , _R_meta ))+    end+    return ret+end++function _reader:int32_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_int32(cobj , key , i))+    end+    return ret+end++function _reader:int64_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_int64(cobj , key , i))+    end+    return ret+end++function _reader:int52_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_int52(cobj , key , i))+    end+    return ret+end++function _reader:uint52_repeated(key)+    local cobj = self._CObj+    local n = c._rmessage_size(cobj , key)+    local ret = {}+    for i=0,n-1 do+        tinsert(ret,  c._rmessage_uint52(cobj , key , i))+    end+    return ret+end++_reader[1] = function(msg) return _reader.int end+_reader[2] = function(msg) return _reader.real end+_reader[3] = function(msg) return _reader.bool end+_reader[4] = function(msg) return _reader.string end+_reader[5] = function(msg) return _reader.string end+_reader[6] = function(msg)+    local message = _reader.message+    return  function(self,key)+            return message(self, key, msg)+        end+end+_reader[7] = function(msg) return _reader.int64 end+_reader[8] = function(msg) return _reader.int32 end+_reader[9] = _reader[5]+_reader[10] = function(msg) return _reader.int52 end+_reader[11] = function(msg) return _reader.uint52 end++_reader[128+1] = function(msg) return _reader.int_repeated end+_reader[128+2] = function(msg) return _reader.real_repeated end+_reader[128+3] = function(msg) return _reader.bool_repeated end+_reader[128+4] = function(msg) return _reader.string_repeated end+_reader[128+5] = function(msg) return _reader.string_repeated end+_reader[128+6] = function(msg)+    local message = _reader.message_repeated+    return  function(self,key)+            return message(self, key, msg)+        end+end+_reader[128+7] = function(msg) return _reader.int64_repeated end+_reader[128+8] = function(msg) return _reader.int32_repeated end+_reader[128+9] = _reader[128+5]+_reader[128+10] = function(msg) return _reader.int52_repeated end+_reader[128+11] = function(msg) return _reader.uint52_repeated end++local _decode_type_meta = {}++function _decode_type_meta:__index(key)+    local t, msg = c._env_type(P, self._CType, key)+    local func = assert(_reader[t],key)(msg)+    self[key] = func+    return func+end++setmetatable(decode_type_cache , {+    __index = function(self, key)+        local v = setmetatable({ _CType = key } , _decode_type_meta)+        self[key] = v+        return v+    end+})++local function decode_message( message , buffer, length)+    local rmessage = c._rmessage_new(P, message, buffer, length)+    if rmessage then+        local self = {+            _CObj = rmessage,+            _CType = message,+        }+        c._add_rmessage(GC,rmessage)+        return setmetatable( self , _R_meta )+    end+end++----------- encode ----------------++local encode_type_cache = {}++local function encode_message(CObj, message_type, t)+    local type = encode_type_cache[message_type]+    for k,v in pairs(t) do+        local func = type[k]+        func(CObj, k , v)+    end+end++local _writer = {+    int = c._wmessage_integer,+    real = c._wmessage_real,+    enum = c._wmessage_string,+    string = c._wmessage_string,+    int64 = c._wmessage_int64,+    int32 = c._wmessage_int32,+    int52 = c._wmessage_int52,+    uint52 = c._wmessage_uint52,+}++function _writer:bool(k,v)+    c._wmessage_integer(self, k, v and 1 or 0)+end++function _writer:message(k, v , message_type)+    local submessage = c._wmessage_message(self, k)+    encode_message(submessage, message_type, v)+end++function _writer:int_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_integer(self,k,v)+    end+end++function _writer:real_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_real(self,k,v)+    end+end++function _writer:bool_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_integer(self, k, v and 1 or 0)+    end+end++function _writer:string_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_string(self,k,v)+    end+end++function _writer:message_repeated(k,v, message_type)+    for _,v in ipairs(v) do+        local submessage = c._wmessage_message(self, k)+        encode_message(submessage, message_type, v)+    end+end++function _writer:int32_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_int32(self,k,v)+    end+end++function _writer:int64_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_int64(self,k,v)+    end+end++function _writer:int52_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_int52(self,k,v)+    end+end++function _writer:uint52_repeated(k,v)+    for _,v in ipairs(v) do+        c._wmessage_uint52(self,k,v)+    end+end++_writer[1] = function(msg) return _writer.int end+_writer[2] = function(msg) return _writer.real end+_writer[3] = function(msg) return _writer.bool end+_writer[4] = function(msg) return _writer.string end+_writer[5] = function(msg) return _writer.string end+_writer[6] = function(msg)+    local message = _writer.message+    return  function(self,key , v)+            return message(self, key, v, msg)+        end+end+_writer[7] = function(msg) return _writer.int64 end+_writer[8] = function(msg) return _writer.int32 end+_writer[9] = _writer[5]+_writer[10] = function(msg) return _writer.int52 end+_writer[11] = function(msg) return _writer.uint52 end++_writer[128+1] = function(msg) return _writer.int_repeated end+_writer[128+2] = function(msg) return _writer.real_repeated end+_writer[128+3] = function(msg) return _writer.bool_repeated end+_writer[128+4] = function(msg) return _writer.string_repeated end+_writer[128+5] = function(msg) return _writer.string_repeated end+_writer[128+6] = function(msg)+    local message = _writer.message_repeated+    return  function(self,key, v)+            return message(self, key, v, msg)+        end+end+_writer[128+7] = function(msg) return _writer.int64_repeated end+_writer[128+8] = function(msg) return _writer.int32_repeated end+_writer[128+9] = _writer[128+5]+_writer[128+10] = function(msg) return _writer.int52_repeated end+_writer[128+11] = function(msg) return _writer.uint52_repeated end++local _encode_type_meta = {}++function _encode_type_meta:__index(key)+    local t, msg = c._env_type(P, self._CType, key)+    local func = assert(_writer[t],key)(msg)+    self[key] = func+    return func+end++setmetatable(encode_type_cache , {+    __index = function(self, key)+        local v = setmetatable({ _CType = key } , _encode_type_meta)+        self[key] = v+        return v+    end+})++function encode( message, t , func , ...)+    local encoder = c._wmessage_new(P, message)+    assert(encoder ,  message)+    encode_message(encoder, message, t)+    if func then+        local buffer, len = c._wmessage_buffer(encoder)+        local ret = func(buffer, len, ...)+        c._wmessage_delete(encoder)+        return ret+    else+        local s = c._wmessage_buffer_string(encoder)+        c._wmessage_delete(encoder)+        return s+    end+end++--------- unpack ----------++local _pattern_type = {+    [1] = {"%d","i"},+    [2] = {"%F","r"},+    [3] = {"%d","b"},+    [4] = {"%d","i"},+    [5] = {"%s","s"},+    [6] = {"%s","m"},+    [7] = {"%D","x"},+    [8] = {"%d","p"},+    [10] =  {"%D","d"},+    [11] =  {"%D","u"},+    [128+1] = {"%a","I"},+    [128+2] = {"%a","R"},+    [128+3] = {"%a","B"},+    [128+4] = {"%a","I"},+    [128+5] = {"%a","S"},+    [128+6] = {"%a","M"},+    [128+7] = {"%a","X"},+    [128+8] = {"%a","P"},+    [128+10] = {"%a", "D" },+    [128+11] = {"%a", "U" },+}++_pattern_type[9] = _pattern_type[5]+_pattern_type[128+9] = _pattern_type[128+5]+++local function _pattern_create(pattern)+    local iter = string.gmatch(pattern,"[^ ]+")+    local message = iter()+    local cpat = {}+    local lua = {}+    for v in iter do+        local tidx = c._env_type(P, message, v)+        local t = _pattern_type[tidx]+        assert(t,tidx)+        tinsert(cpat,v .. " " .. t[1])+        tinsert(lua,t[2])+    end+    local cobj = c._pattern_new(P, message , "@" .. table.concat(cpat," "))+    if cobj == nil then+        return+    end+    c._add_pattern(GC, cobj)+    local pat = {+        CObj = cobj,+        format = table.concat(lua),+        size = 0+    }+    pat.size = c._pattern_size(pat.format)++    return pat+end++setmetatable(_pattern_cache, {+    __index = function(t, key)+        local v = _pattern_create(key)+        t[key] = v+        return v+    end+})++function unpack(pattern, buffer, length)+    local pat = _pattern_cache[pattern]+    return c._pattern_unpack(pat.CObj , pat.format, pat.size, buffer, length)+end++function pack(pattern, ...)+    local pat = _pattern_cache[pattern]+    return c._pattern_pack(pat.CObj, pat.format, pat.size , ...)+end++function check(typename , field)+    if field == nil then+        return c._env_type(P,typename)+    else+        return c._env_type(P,typename,field) ~=0+    end+end++--------------++local default_cache = {}++-- todo : clear default_cache, v._CObj++local function default_table(typename)+    local v = default_cache[typename]+    if v then+        return v+    end++    v = { __index = assert(decode_message(typename , "")) }++    default_cache[typename]  = v+    return v+end++local decode_message_mt = {}++local function decode_message_cb(typename, buffer)+    return setmetatable ( { typename, buffer } , decode_message_mt)+end++function decode(typename, buffer, length)+    local ret = {}+    local ok = c._decode(P, decode_message_cb , ret , typename, buffer, length)+    if ok then+        return setmetatable(ret , default_table(typename))+    else+        return false , c._last_error(P)+    end+end++local function expand(tbl)+    local typename = rawget(tbl , 1)+    local buffer = rawget(tbl , 2)+    tbl[1] , tbl[2] = nil , nil+    assert(c._decode(P, decode_message_cb , tbl , typename, buffer), typename)+    setmetatable(tbl , default_table(typename))+end++function decode_message_mt.__index(tbl, key)+    expand(tbl)+    return tbl[key]+end++function decode_message_mt.__pairs(tbl)+    expand(tbl)+    return pairs(tbl)+end++local function set_default(typename, tbl)+    for k,v in pairs(tbl) do+        if type(v) == "table" then+            local t, msg = c._env_type(P, typename, k)+            if t == 6 then+                set_default(msg, v)+            elseif t == 128+6 then+                for _,v in ipairs(v) do+                    set_default(msg, v)+                end+            end+        end+    end+    return setmetatable(tbl , default_table(typename))+end++function register(buffer)+    c._env_register(P, buffer)+end++function register_file(filename)+    local f = assert(io.open(filename , "rb"))+    local buffer = f:read "*a"+    c._env_register(P, buffer)+    f:close()+end++default=set_default+|]