https://github.com/sean-lin/protoc-gen-lua
https://github.com/djungelorm/protobuf-lua
sudo apt-get install python-protobuf
/usr/local/bin/protoc-gen-lua
which is symlinked to /usr/local/lib/luarocks/rocks/protobuf/1.1.1-0/protoc-plugin/protoc-gen-lua
https://github.com/urbanairship/protobuf-lua
https://github.com/indygreg/lua-protobuf
https://github.com/haberman/upb
https://github.com/starwing/lua-protobuf
This project offers a simple C library for basic protobuf wire format encode/decode, it splits to several modules: - pb.decoder: a wire format decode module. - pb.buffer: a buffer implement that use to encode basic types into protobuf's wire format. It also can be used to support streaming decode protobuf data. - pb.conv: a module to convert between integers in protobuf. - pb.io: a module to support binary mode read/write to stdin/stdout.
https://github.com/Neopallium/lua-pb
-- ------------------------------------------- -- @return string with message dump local function dumpRawProtoc (binMsg) local p = io.popen ("protoc --decode_raw", "w") local stdout if p then p:write(binMsg) local stdout = p:read("*a") p:close() end return stdout end
local pb = require 'pb' -- loading 'pb' module will replace 'require' function -- now .proto files are automatically loaded by require. local proto = require 'protos.messages' -- load 'protos/messages.proto' -- Two methods of message creation -- 1) direct assign local protoMsg = proto.Message() protoMsg.deviceId = 0x1234 -- simple type value protoMsg.deviceType = 'MODEM' -- enum value protoMsg.repeatedSubMessage = { { id = 'TEMPERATURE', value = 34 }, { id = 'WIND', value = 2 } } protoMsg.subMessage.serialNumber = '123456-1234' protoMsg.subMessage.version = '2' -- 2) Initialize from structure local luaData = { deviceId = 0x1234, deviceType = 'MODEM', repeatedSubMessage = { { id = 'TEMPERATURE', value = 34 }, { id = 'WIND', value = 2 } }, subMessage = { serialNumber = '123456-1234', version = '2' } } local protoMsg = proto.Message(luaData) -- initialize from luaData -- 3) Still possible to directly modify, add values into message protoMsg.deviceId = 0xdeadbeef local binProtoMsg = protoMsg:Serialize() -- binProtoMsg is string print (binProtoMsh:len()) local dumpProtoMsg = protoMsg:SerializePartial('text') local receivedProtoMsg = proto.Message() if receivedProtoMsh == nil then error ("Malformed message") end receivedProtoMsg:Parse(binProtoMsg) print (receivedProtoMsg:SerializePartial('text'))
Raw dump of protobuf message (.proto files not needed)
local function dump_fields(unknown) local o = "" for i, v in ipairs(unknown) do o = o..string.format("#%02d Tag=[%2d] Wire=[%2d] %q\n", i, v.tag, v.wire, tostring(v.value)) if type (v.value) == 'table' then o = o..dump_fields(v.value) end end return o end -- ------------------------------------------- -- @return string with message dump function PD:pbDumpRawPB(binMsg) local msg, off = pb.decode_raw(binMsg) return dump_fields(msg.unknown_fields) end
18446744073709551615 is exactly 2^64-1
in LuaJIT 64bit numbers are stored as double, so some precision is lost:
print (0xFFFFFFFFFFFFFFFF == 0xFFFFFFFFFFFFFF00) true
If library detects LuaJIT with FFI support, it is using FFI cdata to store 64 bit numbers int64_t
or uint64_t
depends on signed
argument passed to make_int64_func
.
If no LuaJIT is used, big values are represented as 8 bytes strings.
local pb = require"pb" local make_int64 = pb.get_make_int64_func() -- make_int64(b8,b7,b6,b5,b4,b3,b2,b1, signed) fakeNodeId = make_int64(0,0,0,0, 0,0,0,1 ) -- or initialize from string local v = \255\255\255\255\255\255\255\255" fakeNodeId = make_int65(v:byte(1,8)) print (fakeNodeId) -- prints: '1ULL' fakeNodeIs = fakeNodeId * 22 print (fakeNodeId) -- prints: '22ULL'
But library encoder doesn't work:
luaData = { ["deviceId"] = 1.844674407371e+19; }; binProtoMsg= 0000 08 00 .. binProtoMsg decoded=deviceId: 0
No documentation. Poor examples. Need to dig in sources to familiarize.
First, proto files needs to be compile with protoc
compile with lua output plugin.
For messages.proto
corresponding lua file messages_pb.lua
will be created.
API:
Other internal methods:
p = require 'messages_pb' local message = p.Message() message.deviceId = 0xdeadbeef -- assign int value message.code = p.Code.OK -- assign enum value (defined in Code enum) message.repeatedSubMessage:add() message.repeatedSubMessage[1].ts = 12345 -- assign int value message.repeatedSubMessage:add() message.repeatedSubMessage[2].ts = 6789 -- assign int value print (message:SerializeToString())