mirror of
https://github.com/cloudwu/skynet.git
synced 2026-07-25 04:33:05 +00:00
remove lpeg & pbc
This commit is contained in:
@@ -1,592 +0,0 @@
|
||||
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 = {}
|
||||
|
||||
local function clear_pat()
|
||||
for _,v in pairs(_pattern_cache) do
|
||||
c._pattern_delete(v.CObj)
|
||||
end
|
||||
end
|
||||
|
||||
local P = c._env_new()
|
||||
setmetatable(_M , {
|
||||
__gc = function(t)
|
||||
clear_pat()
|
||||
c._env_delete(P)
|
||||
end })
|
||||
|
||||
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 function link_parent(self, parent)
|
||||
local link = rawget(parent, _Children)
|
||||
if link == nil then
|
||||
link = {}
|
||||
rawset(parent, "_Children" , link)
|
||||
end
|
||||
tinsert(link, self)
|
||||
end
|
||||
|
||||
local function remove_cobj(self)
|
||||
self._CObj = nil
|
||||
setmetatable(self, nil)
|
||||
local children = self._Children
|
||||
if children then
|
||||
for _,v in ipairs(children) do
|
||||
remove_cobj(v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function delete_all(self)
|
||||
c._rmessage_delete(self._CObj)
|
||||
remove_cobj(self)
|
||||
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 _R_metagc = {
|
||||
__index = _R_meta.__index
|
||||
}
|
||||
|
||||
_R_metagc.__gc = assert(delete_all)
|
||||
|
||||
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,
|
||||
}
|
||||
return setmetatable( self , _R_metagc )
|
||||
end
|
||||
end
|
||||
|
||||
--close_decoder = assert(delete_all)
|
||||
|
||||
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
|
||||
|
||||
----------- 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)
|
||||
func(buffer, len)
|
||||
c._wmessage_delete(encoder)
|
||||
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
|
||||
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 = setmetatable({} , {__mode = "kv"})
|
||||
|
||||
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
|
||||
|
||||
|
||||
default=set_default
|
||||
@@ -1,397 +0,0 @@
|
||||
-----------------------
|
||||
-- simple proto parser
|
||||
-----------------------
|
||||
|
||||
local lpeg = require "lpeg"
|
||||
local P = lpeg.P
|
||||
local S = lpeg.S
|
||||
local R = lpeg.R
|
||||
local C = lpeg.C
|
||||
local Ct = lpeg.Ct
|
||||
local Cg = lpeg.Cg
|
||||
local Cc = lpeg.Cc
|
||||
local V = lpeg.V
|
||||
|
||||
local next = next
|
||||
local error = error
|
||||
local tonumber = tonumber
|
||||
local pairs = pairs
|
||||
local ipairs = ipairs
|
||||
local rawset = rawset
|
||||
local tinsert = table.insert
|
||||
local smatch = string.match
|
||||
local sbyte = string.byte
|
||||
|
||||
local internal_type = {
|
||||
double = "TYPE_DOUBLE",
|
||||
float = "TYPE_FLOAT",
|
||||
uint64 = "TYPE_UINT64",
|
||||
int = "TYPE_INT32",
|
||||
int32 = "TYPE_INT32",
|
||||
int64 = "TYPE_INT64",
|
||||
fixed64 = "TYPE_FIXED64",
|
||||
fixed32 = "TYPE_FIXED32",
|
||||
bool = "TYPE_BOOL",
|
||||
string = "TYPE_STRING",
|
||||
bytes = "TYPE_BYTES",
|
||||
uint32 = "TYPE_UINT32",
|
||||
sfixed32 = "TYPE_SFIXED32",
|
||||
sfixed64 = "TYPE_SFIXED64",
|
||||
sint32 = "TYPE_SINT32",
|
||||
sint64 = "TYPE_SINT64",
|
||||
}
|
||||
|
||||
local function count_lines(_,pos, parser_state)
|
||||
if parser_state.pos < pos then
|
||||
parser_state.line = parser_state.line + 1
|
||||
parser_state.pos = pos
|
||||
end
|
||||
return pos
|
||||
end
|
||||
|
||||
local exception = lpeg.Cmt( lpeg.Carg(1) , function ( _ , pos, parser_state)
|
||||
error( "syntax error at [" .. (parser_state.file or "") .."] (" .. parser_state.line ..")" )
|
||||
return pos
|
||||
end)
|
||||
|
||||
local eof = P(-1)
|
||||
local newline = lpeg.Cmt((P"\n" + "\r\n") * lpeg.Carg(1) ,count_lines)
|
||||
local line_comment = "//" * (1 - newline) ^0 * (newline + eof)
|
||||
local blank = S" \t" + newline + line_comment
|
||||
local blank0 = blank ^ 0
|
||||
local blanks = blank ^ 1
|
||||
local alpha = R"az" + R"AZ" + "_"
|
||||
local alnum = alpha + R"09"
|
||||
local str_c = (1 - S("\\\"")) + P("\\") * 1
|
||||
local str = P"\"" * C(str_c^0) * "\""
|
||||
local dotname = ("." * alpha * alnum ^ 0) ^ 0
|
||||
local typename = C(alpha * alnum ^ 0 * dotname)
|
||||
local name = C(alpha * alnum ^ 0)
|
||||
local filename = C((alnum + "/" + "." + "-")^1)
|
||||
local id = R"09" ^ 1 / tonumber + "max" * Cc(-1)
|
||||
local bool = "true" * Cc(true) + "false" * Cc(false)
|
||||
local value = str + bool + name + id
|
||||
local patterns = {}
|
||||
|
||||
local enum_item = Cg(name * blank0 * "=" * blank0 * id * blank0 * ";" * blank0)
|
||||
|
||||
local function insert(tbl, k,v)
|
||||
tinsert(tbl, { name = k , number = v })
|
||||
return tbl
|
||||
end
|
||||
|
||||
patterns.ENUM = Ct(Cg("enum","type") * blanks * Cg(typename,"name") * blank0 *
|
||||
"{" * blank0 *
|
||||
Cg(lpeg.Cf(Ct"" * enum_item^1 , insert),"value")
|
||||
* "}" * blank0)
|
||||
|
||||
local prefix_field = P"required" * Cc"LABEL_REQUIRED" +
|
||||
P"optional" * Cc"LABEL_OPTIONAL" +
|
||||
P"repeated" * Cc"LABEL_REPEATED"
|
||||
local postfix_pair = blank0 * Cg(name * blank0 * "=" * blank0 * value * blank0)
|
||||
local postfix_pair_2 = blank0 * "," * postfix_pair
|
||||
local postfix_field = "[" * postfix_pair * postfix_pair_2^0 * blank0 * "]"
|
||||
local options = lpeg.Cf(Ct"" * postfix_field , rawset) ^ -1
|
||||
|
||||
local function setoption(t, options)
|
||||
if next(options) then
|
||||
t.options = options
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local message_field = lpeg.Cf (
|
||||
Ct( Cg(prefix_field,"label") * blanks *
|
||||
Cg(typename,"type_name") * blanks *
|
||||
Cg(name,"name") * blank0 * "=" * blank0 *
|
||||
Cg(id,"number")
|
||||
) * blank0 * options ,
|
||||
setoption) * blank0 * ";" * blank0
|
||||
|
||||
local extensions = Ct(
|
||||
Cg("extensions" , "type") * blanks *
|
||||
Cg(id,"start") * blanks * "to" * blanks *
|
||||
Cg(id,"end") * blank0 * ";" * blank0
|
||||
)
|
||||
|
||||
patterns.EXTEND = Ct(
|
||||
Cg("extend", "type") * blanks *
|
||||
Cg(typename, "name") * blank0 * "{" * blank0 *
|
||||
Cg(Ct((message_field) ^ 1),"extension") * "}" * blank0
|
||||
)
|
||||
|
||||
patterns.MESSAGE = P { Ct(
|
||||
Cg("message","type") * blanks *
|
||||
Cg(typename,"name") * blank0 * "{" * blank0 *
|
||||
Cg(Ct((message_field + patterns.ENUM + extensions + patterns.EXTEND + V(1)) ^ 1),"items") * "}" * blank0
|
||||
) }
|
||||
|
||||
patterns.OPTION = Ct(
|
||||
Cg("option" , "type") * blanks *
|
||||
Cg(name, "name") * blank0 * "=" * blank0 *
|
||||
Cg(value, "value")
|
||||
) * blank0 * ";" * blank0
|
||||
|
||||
patterns.IMPORT = Ct( Cg("import" , "type") * blanks * Cg(filename, "name") ) * blank0
|
||||
|
||||
patterns.PACKAGE = Ct( Cg("package", "type") * blanks * Cg(typename, "name") ) * blank0 * ";" * blank0
|
||||
|
||||
local proto_tbl = { "PROTO" }
|
||||
|
||||
do
|
||||
local k, v = next(patterns)
|
||||
local p = V(k)
|
||||
proto_tbl[k] = v
|
||||
for k,v in next , patterns , k do
|
||||
proto_tbl[k] = v
|
||||
p = p + V(k)
|
||||
end
|
||||
proto_tbl.PROTO = Ct(blank0 * p ^ 1)
|
||||
end
|
||||
|
||||
local proto = P(proto_tbl)
|
||||
|
||||
local deal = {}
|
||||
|
||||
function deal:import(v)
|
||||
self.dependency = self.dependency or {}
|
||||
tinsert(self.dependency , v.name)
|
||||
end
|
||||
|
||||
function deal:package(v)
|
||||
self.package = v.name
|
||||
end
|
||||
|
||||
function deal:enum(v)
|
||||
self.enum_type = self.enum_type or {}
|
||||
tinsert(self.enum_type , v)
|
||||
end
|
||||
|
||||
function deal:option(v)
|
||||
self.options = self.options or {}
|
||||
self.options[v.name] = v.value
|
||||
end
|
||||
|
||||
function deal:extend(v)
|
||||
self.extension = self.extension or {}
|
||||
local extendee = v.name
|
||||
for _,v in ipairs(v.extension) do
|
||||
v.extendee = extendee
|
||||
v.type = internal_type[v.type_name]
|
||||
if v.type then
|
||||
v.type_name = nil
|
||||
end
|
||||
tinsert(self.extension , v)
|
||||
end
|
||||
end
|
||||
|
||||
function deal:extensions(v)
|
||||
self.extension_range = self.extension_range or {}
|
||||
tinsert(self.extension_range, v)
|
||||
end
|
||||
|
||||
local function _add_nested_message(self, item)
|
||||
if item.type == nil then
|
||||
item.type = internal_type[item.type_name]
|
||||
if item.type then
|
||||
item.type_name = nil
|
||||
end
|
||||
self.field = self.field or {}
|
||||
tinsert(self.field, item)
|
||||
else
|
||||
local f = deal[item.type]
|
||||
item.type = nil
|
||||
f(self , item)
|
||||
end
|
||||
end
|
||||
|
||||
function deal:message(v)
|
||||
self.nested_type = self.nested_type or {}
|
||||
local m = { name = v.name }
|
||||
tinsert(self.nested_type , m)
|
||||
for _,v in ipairs(v.items) do
|
||||
_add_nested_message(m, v)
|
||||
end
|
||||
end
|
||||
|
||||
local function fix(r)
|
||||
local p = {}
|
||||
for _,v in ipairs(r) do
|
||||
local f = deal[v.type]
|
||||
v.type = nil
|
||||
f(p , v)
|
||||
end
|
||||
|
||||
p.message_type = p.nested_type
|
||||
p.nested_type = nil
|
||||
|
||||
return p
|
||||
end
|
||||
|
||||
--- fix message name
|
||||
|
||||
local NULL = {}
|
||||
|
||||
local function _match_name(namespace , n , all)
|
||||
if sbyte(n) == 46 then
|
||||
return n
|
||||
end
|
||||
|
||||
repeat
|
||||
local name = namespace .. "." .. n
|
||||
if all[name] then
|
||||
return name
|
||||
end
|
||||
namespace = smatch(namespace,"(.*)%.[%w_]+$")
|
||||
until namespace == nil
|
||||
end
|
||||
|
||||
local function _fix_field(namespace , field, all)
|
||||
local type_name = field.type_name
|
||||
if type_name == "" then
|
||||
field.type_name = nil
|
||||
return
|
||||
elseif type_name == nil then
|
||||
return
|
||||
end
|
||||
|
||||
local full_name = assert(_match_name(namespace, field.type_name, all) , field.type_name , all)
|
||||
|
||||
field.type_name = full_name
|
||||
field.type = all[full_name]
|
||||
|
||||
local options = field.options
|
||||
if options then
|
||||
if options.default then
|
||||
field.default_value = tostring(options.default)
|
||||
options.default = nil
|
||||
end
|
||||
if next(options) == nil then
|
||||
field.options = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function _fix_extension(namespace, ext, all)
|
||||
for _,field in ipairs(ext or NULL) do
|
||||
field.extendee = assert(_match_name(namespace, field.extendee,all),field.extendee)
|
||||
_fix_field(namespace , field , all)
|
||||
end
|
||||
end
|
||||
|
||||
local function _fix_message(msg , all)
|
||||
for _,field in ipairs(msg.field or NULL) do
|
||||
_fix_field(assert(all[msg],msg.name) , field , all)
|
||||
end
|
||||
for _,nest in ipairs(msg.nested_type or NULL) do
|
||||
_fix_message(nest , all)
|
||||
end
|
||||
_fix_extension(all[msg] , msg.extension , all)
|
||||
end
|
||||
|
||||
local function _fix_typename(file , all)
|
||||
for _,message in ipairs(file.message_type or NULL) do
|
||||
_fix_message(message , all)
|
||||
end
|
||||
_fix_extension(file.package , file.extension , all)
|
||||
end
|
||||
|
||||
--- merge messages
|
||||
|
||||
local function _enum_fullname(prefix, enum , all)
|
||||
local fullname
|
||||
if sbyte(enum.name) == 46 then
|
||||
fullname = enum.name
|
||||
else
|
||||
fullname = prefix .. "." .. enum.name
|
||||
end
|
||||
all[fullname] = "TYPE_ENUM"
|
||||
all[enum] = fullname
|
||||
end
|
||||
|
||||
local function _message_fullname(prefix , msg , all)
|
||||
local fullname
|
||||
if sbyte(msg.name) == 46 then
|
||||
fullname = msg.name
|
||||
else
|
||||
fullname = prefix .. "." .. msg.name
|
||||
end
|
||||
all[fullname] = "TYPE_MESSAGE"
|
||||
all[msg] = fullname
|
||||
for _,nest in ipairs(msg.nested_type or NULL) do
|
||||
_message_fullname(fullname , nest , all)
|
||||
end
|
||||
for _,enum in ipairs(msg.enum_type or NULL) do
|
||||
_enum_fullname(fullname , enum , all)
|
||||
end
|
||||
end
|
||||
|
||||
local function _gen_fullname(file , all)
|
||||
local prefix = ""
|
||||
if file.package then
|
||||
prefix = "." .. file.package
|
||||
end
|
||||
for _,message in ipairs(file.message_type or NULL) do
|
||||
_message_fullname(prefix , message , all)
|
||||
end
|
||||
for _,enum in ipairs(file.enum_type or NULL) do
|
||||
_enum_fullname(prefix , enum , all)
|
||||
end
|
||||
end
|
||||
|
||||
--- parser
|
||||
|
||||
local parser = {}
|
||||
|
||||
local function parser_one(text,filename)
|
||||
local state = { file = filename, pos = 0, line = 1 }
|
||||
local r = lpeg.match(proto * -1 + exception , text , 1, state )
|
||||
local t = fix(r)
|
||||
return t
|
||||
end
|
||||
|
||||
function parser.parser(text,filename)
|
||||
local t = parser_one(text,filename)
|
||||
local all = {}
|
||||
_gen_fullname(t,all)
|
||||
_fix_typename(t , all)
|
||||
return t
|
||||
end
|
||||
|
||||
local pb = require "protobuf"
|
||||
|
||||
function parser.register(fileset , path)
|
||||
local all = {}
|
||||
local files = {}
|
||||
if type(fileset) == "string" then
|
||||
fileset = { fileset }
|
||||
end
|
||||
for _, filename in ipairs(fileset) do
|
||||
local fullname
|
||||
if path then
|
||||
fullname = path .. "/" .. filename
|
||||
else
|
||||
fullname = filename
|
||||
end
|
||||
local f = assert(io.open(fullname , "r"))
|
||||
local buffer = f:read "*a"
|
||||
f:close()
|
||||
local t = parser_one(buffer,filename)
|
||||
_gen_fullname(t,all)
|
||||
t.name = filename
|
||||
tinsert(files , t)
|
||||
end
|
||||
for _,file in ipairs(files) do
|
||||
_fix_typename(file,all)
|
||||
end
|
||||
|
||||
local pbencode = pb.encode("google.protobuf.FileDescriptorSet" , { file = files })
|
||||
|
||||
if pbencode == nil then
|
||||
error(pb.lasterror())
|
||||
end
|
||||
pb.register(pbencode)
|
||||
return files
|
||||
end
|
||||
|
||||
return parser
|
||||
Reference in New Issue
Block a user