├── .gitignore ├── protobuf ├── Makefile ├── listener.lua ├── descriptor.lua ├── containers.lua ├── type_checkers.lua ├── text_format.lua ├── wire_format.lua ├── decoder.lua ├── pb.c ├── encoder.lua └── protobuf.lua ├── example ├── person.proto └── test.lua ├── LICENSE ├── README.md └── plugin ├── plugin_pb2.py └── protoc-gen-lua /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.so 3 | -------------------------------------------------------------------------------- /protobuf/Makefile: -------------------------------------------------------------------------------- 1 | SRC=pb.c 2 | 3 | TARGET=pb.so 4 | CFLAGS=`pkg-config --cflags lua5.1` -std=gnu99 5 | LDFLAGS=`pkg-config --libs lua5.1` 6 | 7 | all:$(TARGET) 8 | 9 | $(TARGET):$(SRC) 10 | gcc -O3 -shared -fPIC $(SRC) $(CFLAGS) $(LDFLAGS) -o $@ 11 | -------------------------------------------------------------------------------- /example/person.proto: -------------------------------------------------------------------------------- 1 | message Person { 2 | required int32 id = 1; 3 | required string name = 2; 4 | optional string email = 3; 5 | 6 | extensions 10 to max; 7 | } 8 | 9 | message Phone { 10 | extend Person { repeated Phone phones = 10;} 11 | enum PHONE_TYPE{ 12 | MOBILE = 1; 13 | HOME = 2; 14 | } 15 | optional string num = 1; 16 | optional PHONE_TYPE type = 2; 17 | } 18 | -------------------------------------------------------------------------------- /example/test.lua: -------------------------------------------------------------------------------- 1 | package.path = package.path .. ';../protobuf/?.lua' 2 | package.cpath = package.cpath .. ';../protobuf/?.so' 3 | 4 | require 'person_pb' 5 | 6 | local person= person_pb.Person() 7 | person.id = 1000 8 | person.name = "Alice" 9 | person.email = "Alice@example.com" 10 | 11 | local home = person.Extensions[person_pb.Phone.phones]:add() 12 | home.num = "2147483647" 13 | home.type = person_pb.Phone.HOME 14 | 15 | local data = person:SerializeToString() 16 | 17 | local msg = person_pb.Person() 18 | 19 | msg:ParseFromString(data) 20 | print(msg) 21 | -------------------------------------------------------------------------------- /protobuf/listener.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: listener.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年08月02日 17时35分25秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | local setmetatable = setmetatable 19 | 20 | module "listener" 21 | 22 | local _null_listener = { 23 | Modified = function() 24 | end 25 | } 26 | 27 | function NullMessageListener() 28 | return _null_listener 29 | end 30 | 31 | local _listener_meta = { 32 | Modified = function(self) 33 | if self.dirty then 34 | return 35 | end 36 | if self._parent_message then 37 | self._parent_message:_Modified() 38 | end 39 | end 40 | } 41 | _listener_meta.__index = _listener_meta 42 | 43 | function Listener(parent_message) 44 | local o = {} 45 | o.__mode = "v" 46 | o._parent_message = parent_message 47 | o.dirty = false 48 | return setmetatable(o, _listener_meta) 49 | end 50 | 51 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, sean-lin 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of the {organization} nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | protoc-gen-lua 2 | ============== 3 | 4 | Google's Protocol Buffers project, ported to Lua 5 | 6 | "[Protocol Buffers](http://code.google.com/p/protobuf/)" is a binary serialization format and technology, released to the open source community by Google in 2008. 7 | 8 | There are various implementations of Protocol Buffers and this is for Lua. 9 | 10 | ## Install 11 | 12 | Install python runtime and the protobuf 2.3 for python. 13 | 14 | checkout the code. 15 | 16 | Compile the C code: 17 | 18 | `$cd protobuf && make` 19 | 20 | Make a link to protoc-gen-lua in your $PATH: 21 | 22 | `$cd /usr/local/bin && sudo ln -s /path/to/protoc-gen-lua/plugin/protoc-gen-lua` 23 | 24 | Then you can compile the .proto like this: 25 | 26 | `protoc --lua_out=./ foo.proto` 27 | 28 | 29 | ## Quick Example 30 | You write a .proto file like this: 31 | 32 | person.proto : 33 | ``` 34 | message Person { 35 | required int32 id = 1; 36 | required string name = 2; 37 | optional string email = 3; 38 | } 39 | ``` 40 | 41 | Then you compile it. 42 | 43 | Then, make sure that protobuf/ in package.cpath and package.path, you use that code like this: 44 | 45 | ``` 46 | require "person_pb" 47 | 48 | -- Serialize Example 49 | local msg = person_pb.Person() 50 | msg.id = 100 51 | msg.name = "foo" 52 | msg.email = "bar" 53 | local pb_data = msg:SerializeToString() 54 | 55 | -- Parse Example 56 | local msg = person_pb.Person() 57 | msg:ParseFromString(pb_data) 58 | print(msg.id, msg.name, msg.email) 59 | ``` 60 | 61 | The API of this library is similar the protobuf library for python. 62 | For a more complete example, read the [python documentation](http://code.google.com/apis/protocolbuffers/docs/pythontutorial.html). 63 | -------------------------------------------------------------------------------- /protobuf/descriptor.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: descriptor.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年08月11日 18时45分43秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | 19 | module "descriptor" 20 | 21 | FieldDescriptor = { 22 | TYPE_DOUBLE = 1, 23 | TYPE_FLOAT = 2, 24 | TYPE_INT64 = 3, 25 | TYPE_UINT64 = 4, 26 | TYPE_INT32 = 5, 27 | TYPE_FIXED64 = 6, 28 | TYPE_FIXED32 = 7, 29 | TYPE_BOOL = 8, 30 | TYPE_STRING = 9, 31 | TYPE_GROUP = 10, 32 | TYPE_MESSAGE = 11, 33 | TYPE_BYTES = 12, 34 | TYPE_UINT32 = 13, 35 | TYPE_ENUM = 14, 36 | TYPE_SFIXED32 = 15, 37 | TYPE_SFIXED64 = 16, 38 | TYPE_SINT32 = 17, 39 | TYPE_SINT64 = 18, 40 | MAX_TYPE = 18, 41 | 42 | -- Must be consistent with C++ FieldDescriptor::CppType enum in 43 | -- descriptor.h. 44 | -- 45 | CPPTYPE_INT32 = 1, 46 | CPPTYPE_INT64 = 2, 47 | CPPTYPE_UINT32 = 3, 48 | CPPTYPE_UINT64 = 4, 49 | CPPTYPE_DOUBLE = 5, 50 | CPPTYPE_FLOAT = 6, 51 | CPPTYPE_BOOL = 7, 52 | CPPTYPE_ENUM = 8, 53 | CPPTYPE_STRING = 9, 54 | CPPTYPE_MESSAGE = 10, 55 | MAX_CPPTYPE = 10, 56 | 57 | -- Must be consistent with C++ FieldDescriptor::Label enum in 58 | -- descriptor.h. 59 | -- 60 | LABEL_OPTIONAL = 1, 61 | LABEL_REQUIRED = 2, 62 | LABEL_REPEATED = 3, 63 | MAX_LABEL = 3 64 | } 65 | -------------------------------------------------------------------------------- /protobuf/containers.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: containers.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年08月02日 16时15分42秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | local setmetatable = setmetatable 19 | local table = table 20 | local rawset = rawset 21 | local error = error 22 | 23 | module "containers" 24 | 25 | local _RCFC_meta = { 26 | add = function(self) 27 | local value = self._message_descriptor._concrete_class() 28 | local listener = self._listener 29 | rawset(self, #self + 1, value) 30 | value:_SetListener(listener) 31 | if listener.dirty == false then 32 | listener:Modified() 33 | end 34 | return value 35 | end, 36 | remove = function(self, key) 37 | local listener = self._listener 38 | table.remove(self, key) 39 | listener:Modified() 40 | end, 41 | __newindex = function(self, key, value) 42 | error("RepeatedCompositeFieldContainer Can't set value directly") 43 | end 44 | } 45 | _RCFC_meta.__index = _RCFC_meta 46 | 47 | function RepeatedCompositeFieldContainer(listener, message_descriptor) 48 | local o = { 49 | _listener = listener, 50 | _message_descriptor = message_descriptor 51 | } 52 | return setmetatable(o, _RCFC_meta) 53 | end 54 | 55 | local _RSFC_meta = { 56 | append = function(self, value) 57 | self._type_checker(value) 58 | rawset(self, #self + 1, value) 59 | self._listener:Modified() 60 | end, 61 | remove = function(self, key) 62 | table.remove(self, key) 63 | self._listener:Modified() 64 | end, 65 | __newindex = function(self, key, value) 66 | error("RepeatedCompositeFieldContainer Can't set value directly") 67 | end 68 | } 69 | _RSFC_meta.__index = _RSFC_meta 70 | 71 | function RepeatedScalarFieldContainer(listener, type_checker) 72 | local o = {} 73 | o._listener = listener 74 | o._type_checker = type_checker 75 | return setmetatable(o, _RSFC_meta) 76 | end 77 | 78 | 79 | -------------------------------------------------------------------------------- /protobuf/type_checkers.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: type_checkers.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年07月29日 19时30分37秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | 19 | local type = type 20 | local error = error 21 | local string = string 22 | 23 | module "type_checkers" 24 | function TypeChecker(acceptable_types) 25 | local acceptable_types = acceptable_types 26 | 27 | return function(proposed_value) 28 | local t = type(proposed_value) 29 | if acceptable_types[type(proposed_value)] == nil then 30 | error(string.format('%s has type %s, but expected one of: %s', 31 | proposed_value, type(proposed_value), acceptable_types)) 32 | end 33 | end 34 | end 35 | 36 | function Int32ValueChecker() 37 | local _MIN = -2147483648 38 | local _MAX = 2147483647 39 | return function(proposed_value) 40 | if type(proposed_value) ~= 'number' then 41 | error(string.format('%s has type %s, but expected one of: number', 42 | proposed_value, type(proposed_value))) 43 | end 44 | if _MIN > proposed_value or proposed_value > _MAX then 45 | error('Value out of range: ' .. proposed_value) 46 | end 47 | end 48 | end 49 | 50 | function Uint32ValueChecker(IntValueChecker) 51 | local _MIN = 0 52 | local _MAX = 0xffffffff 53 | 54 | return function(proposed_value) 55 | if type(proposed_value) ~= 'number' then 56 | error(string.format('%s has type %s, but expected one of: number', 57 | proposed_value, type(proposed_value))) 58 | end 59 | if _MIN > proposed_value or proposed_value > _MAX then 60 | error('Value out of range: ' .. proposed_value) 61 | end 62 | end 63 | end 64 | 65 | function UnicodeValueChecker() 66 | return function (proposed_value) 67 | if type(proposed_value) ~= 'string' then 68 | error(string.format('%s has type %s, but expected one of: string', proposed_value, type(proposed_value))) 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /protobuf/text_format.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: text_format.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- COMPANY: NetEase 14 | -- CREATED: 2010年08月05日 15时14分13秒 CST 15 | -------------------------------------------------------------------------------- 16 | -- 17 | local string = string 18 | local math = math 19 | local print = print 20 | local getmetatable = getmetatable 21 | local table = table 22 | local ipairs = ipairs 23 | local tostring = tostring 24 | 25 | local descriptor = require "descriptor" 26 | 27 | module "text_format" 28 | 29 | function format(buffer) 30 | local len = string.len( buffer ) 31 | for i = 1, len, 16 do 32 | local text = "" 33 | for j = i, math.min( i + 16 - 1, len ) do 34 | text = string.format( "%s %02x", text, string.byte( buffer, j ) ) 35 | end 36 | print( text ) 37 | end 38 | end 39 | 40 | local FieldDescriptor = descriptor.FieldDescriptor 41 | 42 | msg_format_indent = function(write, msg, indent) 43 | for field, value in msg:ListFields() do 44 | local print_field = function(field_value) 45 | local name = field.name 46 | write(string.rep(" ", indent)) 47 | if field.type == FieldDescriptor.TYPE_MESSAGE then 48 | local extensions = getmetatable(msg)._extensions_by_name 49 | if extensions[field.full_name] then 50 | write("[" .. name .. "] {\n") 51 | else 52 | write(name .. " {\n") 53 | end 54 | msg_format_indent(write, field_value, indent + 4) 55 | write(string.rep(" ", indent)) 56 | write("}\n") 57 | else 58 | write(string.format("%s: %s\n", name, tostring(field_value))) 59 | end 60 | end 61 | if field.label == FieldDescriptor.LABEL_REPEATED then 62 | for _, k in ipairs(value) do 63 | print_field(k) 64 | end 65 | else 66 | print_field(value) 67 | end 68 | end 69 | end 70 | 71 | function msg_format(msg) 72 | local out = {} 73 | local write = function(value) 74 | out[#out + 1] = value 75 | end 76 | msg_format_indent(write, msg, 0) 77 | return table.concat(out) 78 | end 79 | 80 | -------------------------------------------------------------------------------- /protobuf/wire_format.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: wire_format.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- COMPANY: NetEase 14 | -- CREATED: 2010年07月30日 15时59分53秒 CST 15 | -------------------------------------------------------------------------------- 16 | -- 17 | 18 | local pb = require "pb" 19 | module "wire_format" 20 | 21 | WIRETYPE_VARINT = 0 22 | WIRETYPE_FIXED64 = 1 23 | WIRETYPE_LENGTH_DELIMITED = 2 24 | WIRETYPE_START_GROUP = 3 25 | WIRETYPE_END_GROUP = 4 26 | WIRETYPE_FIXED32 = 5 27 | _WIRETYPE_MAX = 5 28 | 29 | 30 | -- yeah, we don't need uint64 31 | local function _VarUInt64ByteSizeNoTag(uint64) 32 | if uint64 <= 0x7f then return 1 end 33 | if uint64 <= 0x3fff then return 2 end 34 | if uint64 <= 0x1fffff then return 3 end 35 | if uint64 <= 0xfffffff then return 4 end 36 | return 5 37 | end 38 | 39 | function PackTag(field_number, wire_type) 40 | return field_number * 8 + wire_type 41 | end 42 | 43 | function UnpackTag(tag) 44 | local wire_type = tag % 8 45 | return (tag - wire_type) / 8, wire_type 46 | end 47 | 48 | ZigZagEncode32 = pb.zig_zag_encode32 49 | ZigZagDecode32 = pb.zig_zag_decode32 50 | ZigZagEncode64 = pb.zig_zag_encode64 51 | ZigZagDecode64 = pb.zig_zag_decode64 52 | 53 | function Int32ByteSize(field_number, int32) 54 | return Int64ByteSize(field_number, int32) 55 | end 56 | 57 | function Int32ByteSizeNoTag(int32) 58 | return _VarUInt64ByteSizeNoTag(int32) 59 | end 60 | 61 | function Int64ByteSize(field_number, int64) 62 | return UInt64ByteSize(field_number, int64) 63 | end 64 | 65 | function UInt32ByteSize(field_number, uint32) 66 | return UInt64ByteSize(field_number, uint32) 67 | end 68 | 69 | function UInt64ByteSize(field_number, uint64) 70 | return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(uint64) 71 | end 72 | 73 | function SInt32ByteSize(field_number, int32) 74 | return UInt32ByteSize(field_number, ZigZagEncode(int32)) 75 | end 76 | 77 | function SInt64ByteSize(field_number, int64) 78 | return UInt64ByteSize(field_number, ZigZagEncode(int64)) 79 | end 80 | 81 | function Fixed32ByteSize(field_number, fixed32) 82 | return TagByteSize(field_number) + 4 83 | end 84 | 85 | function Fixed64ByteSize(field_number, fixed64) 86 | return TagByteSize(field_number) + 8 87 | end 88 | 89 | function SFixed32ByteSize(field_number, sfixed32) 90 | return TagByteSize(field_number) + 4 91 | end 92 | 93 | function SFixed64ByteSize(field_number, sfixed64) 94 | return TagByteSize(field_number) + 8 95 | end 96 | 97 | function FloatByteSize(field_number, flt) 98 | return TagByteSize(field_number) + 4 99 | end 100 | 101 | function DoubleByteSize(field_number, double) 102 | return TagByteSize(field_number) + 8 103 | end 104 | 105 | function BoolByteSize(field_number, b) 106 | return TagByteSize(field_number) + 1 107 | end 108 | 109 | function EnumByteSize(field_number, enum) 110 | return UInt32ByteSize(field_number, enum) 111 | end 112 | 113 | function StringByteSize(field_number, string) 114 | return BytesByteSize(field_number, string) 115 | end 116 | 117 | function BytesByteSize(field_number, b) 118 | return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(#b) + #b 119 | end 120 | 121 | function MessageByteSize(field_number, message) 122 | return TagByteSize(field_number) + _VarUInt64ByteSizeNoTag(message.ByteSize()) + message.ByteSize() 123 | end 124 | 125 | function MessageSetItemByteSize(field_number, msg) 126 | local total_size = 2 * TagByteSize(1) + TagByteSize(2) + TagByteSize(3) 127 | total_size = total_size + _VarUInt64ByteSizeNoTag(field_number) 128 | local message_size = msg.ByteSize() 129 | total_size = total_size + _VarUInt64ByteSizeNoTag(message_size) 130 | total_size = total_size + message_size 131 | return total_size 132 | end 133 | 134 | function TagByteSize(field_number) 135 | return _VarUInt64ByteSizeNoTag(PackTag(field_number, 0)) 136 | end 137 | 138 | -------------------------------------------------------------------------------- /plugin/plugin_pb2.py: -------------------------------------------------------------------------------- 1 | # Generated by the protocol buffer compiler. DO NOT EDIT! 2 | 3 | from google.protobuf import descriptor 4 | from google.protobuf import message 5 | from google.protobuf import reflection 6 | from google.protobuf import descriptor_pb2 7 | # @@protoc_insertion_point(imports) 8 | 9 | 10 | DESCRIPTOR = descriptor.FileDescriptor( 11 | name='google/protobuf/compiler/plugin.proto', 12 | package='google.protobuf.compiler', 13 | serialized_pb='\n%google/protobuf/compiler/plugin.proto\x12\x18google.protobuf.compiler\x1a google/protobuf/descriptor.proto\"}\n\x14\x43odeGeneratorRequest\x12\x18\n\x10\x66ile_to_generate\x18\x01 \x03(\t\x12\x11\n\tparameter\x18\x02 \x01(\t\x12\x38\n\nproto_file\x18\x0f \x03(\x0b\x32$.google.protobuf.FileDescriptorProto\"\xaa\x01\n\x15\x43odeGeneratorResponse\x12\r\n\x05\x65rror\x18\x01 \x01(\t\x12\x42\n\x04\x66ile\x18\x0f \x03(\x0b\x32\x34.google.protobuf.compiler.CodeGeneratorResponse.File\x1a>\n\x04\x46ile\x12\x0c\n\x04name\x18\x01 \x01(\t\x12\x17\n\x0finsertion_point\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x0f \x01(\t') 14 | 15 | 16 | 17 | 18 | _CODEGENERATORREQUEST = descriptor.Descriptor( 19 | name='CodeGeneratorRequest', 20 | full_name='google.protobuf.compiler.CodeGeneratorRequest', 21 | filename=None, 22 | file=DESCRIPTOR, 23 | containing_type=None, 24 | fields=[ 25 | descriptor.FieldDescriptor( 26 | name='file_to_generate', full_name='google.protobuf.compiler.CodeGeneratorRequest.file_to_generate', index=0, 27 | number=1, type=9, cpp_type=9, label=3, 28 | has_default_value=False, default_value=[], 29 | message_type=None, enum_type=None, containing_type=None, 30 | is_extension=False, extension_scope=None, 31 | options=None), 32 | descriptor.FieldDescriptor( 33 | name='parameter', full_name='google.protobuf.compiler.CodeGeneratorRequest.parameter', index=1, 34 | number=2, type=9, cpp_type=9, label=1, 35 | has_default_value=False, default_value=unicode("", "utf-8"), 36 | message_type=None, enum_type=None, containing_type=None, 37 | is_extension=False, extension_scope=None, 38 | options=None), 39 | descriptor.FieldDescriptor( 40 | name='proto_file', full_name='google.protobuf.compiler.CodeGeneratorRequest.proto_file', index=2, 41 | number=15, type=11, cpp_type=10, label=3, 42 | has_default_value=False, default_value=[], 43 | message_type=None, enum_type=None, containing_type=None, 44 | is_extension=False, extension_scope=None, 45 | options=None), 46 | ], 47 | extensions=[ 48 | ], 49 | nested_types=[], 50 | enum_types=[ 51 | ], 52 | options=None, 53 | is_extendable=False, 54 | extension_ranges=[], 55 | serialized_start=101, 56 | serialized_end=226, 57 | ) 58 | 59 | 60 | _CODEGENERATORRESPONSE_FILE = descriptor.Descriptor( 61 | name='File', 62 | full_name='google.protobuf.compiler.CodeGeneratorResponse.File', 63 | filename=None, 64 | file=DESCRIPTOR, 65 | containing_type=None, 66 | fields=[ 67 | descriptor.FieldDescriptor( 68 | name='name', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.name', index=0, 69 | number=1, type=9, cpp_type=9, label=1, 70 | has_default_value=False, default_value=unicode("", "utf-8"), 71 | message_type=None, enum_type=None, containing_type=None, 72 | is_extension=False, extension_scope=None, 73 | options=None), 74 | descriptor.FieldDescriptor( 75 | name='insertion_point', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point', index=1, 76 | number=2, type=9, cpp_type=9, label=1, 77 | has_default_value=False, default_value=unicode("", "utf-8"), 78 | message_type=None, enum_type=None, containing_type=None, 79 | is_extension=False, extension_scope=None, 80 | options=None), 81 | descriptor.FieldDescriptor( 82 | name='content', full_name='google.protobuf.compiler.CodeGeneratorResponse.File.content', index=2, 83 | number=15, type=9, cpp_type=9, label=1, 84 | has_default_value=False, default_value=unicode("", "utf-8"), 85 | message_type=None, enum_type=None, containing_type=None, 86 | is_extension=False, extension_scope=None, 87 | options=None), 88 | ], 89 | extensions=[ 90 | ], 91 | nested_types=[], 92 | enum_types=[ 93 | ], 94 | options=None, 95 | is_extendable=False, 96 | extension_ranges=[], 97 | serialized_start=337, 98 | serialized_end=399, 99 | ) 100 | 101 | _CODEGENERATORRESPONSE = descriptor.Descriptor( 102 | name='CodeGeneratorResponse', 103 | full_name='google.protobuf.compiler.CodeGeneratorResponse', 104 | filename=None, 105 | file=DESCRIPTOR, 106 | containing_type=None, 107 | fields=[ 108 | descriptor.FieldDescriptor( 109 | name='error', full_name='google.protobuf.compiler.CodeGeneratorResponse.error', index=0, 110 | number=1, type=9, cpp_type=9, label=1, 111 | has_default_value=False, default_value=unicode("", "utf-8"), 112 | message_type=None, enum_type=None, containing_type=None, 113 | is_extension=False, extension_scope=None, 114 | options=None), 115 | descriptor.FieldDescriptor( 116 | name='file', full_name='google.protobuf.compiler.CodeGeneratorResponse.file', index=1, 117 | number=15, type=11, cpp_type=10, label=3, 118 | has_default_value=False, default_value=[], 119 | message_type=None, enum_type=None, containing_type=None, 120 | is_extension=False, extension_scope=None, 121 | options=None), 122 | ], 123 | extensions=[ 124 | ], 125 | nested_types=[_CODEGENERATORRESPONSE_FILE, ], 126 | enum_types=[ 127 | ], 128 | options=None, 129 | is_extendable=False, 130 | extension_ranges=[], 131 | serialized_start=229, 132 | serialized_end=399, 133 | ) 134 | 135 | import google.protobuf.descriptor_pb2 136 | 137 | _CODEGENERATORREQUEST.fields_by_name['proto_file'].message_type = google.protobuf.descriptor_pb2._FILEDESCRIPTORPROTO 138 | _CODEGENERATORRESPONSE_FILE.containing_type = _CODEGENERATORRESPONSE; 139 | _CODEGENERATORRESPONSE.fields_by_name['file'].message_type = _CODEGENERATORRESPONSE_FILE 140 | 141 | class CodeGeneratorRequest(message.Message): 142 | __metaclass__ = reflection.GeneratedProtocolMessageType 143 | DESCRIPTOR = _CODEGENERATORREQUEST 144 | 145 | # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorRequest) 146 | 147 | class CodeGeneratorResponse(message.Message): 148 | __metaclass__ = reflection.GeneratedProtocolMessageType 149 | 150 | class File(message.Message): 151 | __metaclass__ = reflection.GeneratedProtocolMessageType 152 | DESCRIPTOR = _CODEGENERATORRESPONSE_FILE 153 | 154 | # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse.File) 155 | DESCRIPTOR = _CODEGENERATORRESPONSE 156 | 157 | # @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse) 158 | 159 | # @@protoc_insertion_point(module_scope) 160 | -------------------------------------------------------------------------------- /protobuf/decoder.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: decoder.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年07月29日 19时30分51秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | local string = string 19 | local table = table 20 | local assert = assert 21 | local ipairs = ipairs 22 | local error = error 23 | local print = print 24 | 25 | local pb = require "pb" 26 | local encoder = require "encoder" 27 | local wire_format = require "wire_format" 28 | module "decoder" 29 | 30 | local _DecodeVarint = pb.varint_decoder 31 | local _DecodeSignedVarint = pb.signed_varint_decoder 32 | 33 | local _DecodeVarint32 = pb.varint_decoder 34 | local _DecodeSignedVarint32 = pb.signed_varint_decoder 35 | 36 | ReadTag = pb.read_tag 37 | 38 | local function _SimpleDecoder(wire_type, decode_value) 39 | return function(field_number, is_repeated, is_packed, key, new_default) 40 | if is_packed then 41 | local DecodeVarint = _DecodeVarint 42 | return function (buffer, pos, pend, message, field_dict) 43 | local value = field_dict[key] 44 | if value == nil then 45 | value = new_default(message) 46 | field_dict[key] = value 47 | end 48 | local endpoint 49 | endpoint, pos = DecodeVarint(buffer, pos) 50 | endpoint = endpoint + pos 51 | if endpoint > pend then 52 | error('Truncated message.') 53 | end 54 | local element 55 | while pos < endpoint do 56 | element, pos = decode_value(buffer, pos) 57 | value[#value + 1] = element 58 | end 59 | if pos > endpoint then 60 | value:remove(#value) 61 | error('Packed element was truncated.') 62 | end 63 | return pos 64 | end 65 | elseif is_repeated then 66 | local tag_bytes = encoder.TagBytes(field_number, wire_type) 67 | local tag_len = #tag_bytes 68 | local sub = string.sub 69 | return function(buffer, pos, pend, message, field_dict) 70 | local value = field_dict[key] 71 | if value == nil then 72 | value = new_default(message) 73 | field_dict[key] = value 74 | end 75 | while 1 do 76 | local element, new_pos = decode_value(buffer, pos) 77 | value:append(element) 78 | pos = new_pos + tag_len 79 | if sub(buffer, new_pos+1, pos) ~= tag_bytes or new_pos >= pend then 80 | if new_pos > pend then 81 | error('Truncated message.') 82 | end 83 | return new_pos 84 | end 85 | end 86 | end 87 | else 88 | return function (buffer, pos, pend, message, field_dict) 89 | field_dict[key], pos = decode_value(buffer, pos) 90 | if pos > pend then 91 | field_dict[key] = nil 92 | error('Truncated message.') 93 | end 94 | return pos 95 | end 96 | end 97 | end 98 | end 99 | 100 | local function _ModifiedDecoder(wire_type, decode_value, modify_value) 101 | local InnerDecode = function (buffer, pos) 102 | local result, new_pos = decode_value(buffer, pos) 103 | return modify_value(result), new_pos 104 | end 105 | return _SimpleDecoder(wire_type, InnerDecode) 106 | end 107 | 108 | local function _StructPackDecoder(wire_type, value_size, format) 109 | local struct_unpack = pb.struct_unpack 110 | 111 | function InnerDecode(buffer, pos) 112 | local new_pos = pos + value_size 113 | local result = struct_unpack(format, buffer, pos) 114 | return result, new_pos 115 | end 116 | return _SimpleDecoder(wire_type, InnerDecode) 117 | end 118 | 119 | local function _Boolean(value) 120 | return value ~= 0 121 | end 122 | 123 | Int32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeSignedVarint32) 124 | EnumDecoder = Int32Decoder 125 | 126 | Int64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeSignedVarint) 127 | 128 | UInt32Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32) 129 | UInt64Decoder = _SimpleDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint) 130 | 131 | SInt32Decoder = _ModifiedDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint32, wire_format.ZigZagDecode32) 132 | SInt64Decoder = _ModifiedDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint, wire_format.ZigZagDecode64) 133 | 134 | Fixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('I')) 135 | Fixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('Q')) 136 | SFixed32Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('i')) 137 | SFixed64Decoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('q')) 138 | FloatDecoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('f')) 139 | DoubleDecoder = _StructPackDecoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('d')) 140 | 141 | 142 | BoolDecoder = _ModifiedDecoder(wire_format.WIRETYPE_VARINT, _DecodeVarint, _Boolean) 143 | 144 | 145 | function StringDecoder(field_number, is_repeated, is_packed, key, new_default) 146 | local DecodeVarint = _DecodeVarint 147 | local sub = string.sub 148 | -- local unicode = unicode 149 | assert(not is_packed) 150 | if is_repeated then 151 | local tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 152 | local tag_len = #tag_bytes 153 | return function (buffer, pos, pend, message, field_dict) 154 | local value = field_dict[key] 155 | if value == nil then 156 | value = new_default(message) 157 | field_dict[key] = value 158 | end 159 | while 1 do 160 | local size, new_pos 161 | size, pos = DecodeVarint(buffer, pos) 162 | new_pos = pos + size 163 | if new_pos > pend then 164 | error('Truncated string.') 165 | end 166 | value:append(sub(buffer, pos+1, new_pos)) 167 | pos = new_pos + tag_len 168 | if sub(buffer, new_pos + 1, pos) ~= tag_bytes or new_pos == pend then 169 | return new_pos 170 | end 171 | end 172 | end 173 | else 174 | return function (buffer, pos, pend, message, field_dict) 175 | local size, new_pos 176 | size, pos = DecodeVarint(buffer, pos) 177 | new_pos = pos + size 178 | if new_pos > pend then 179 | error('Truncated string.') 180 | end 181 | field_dict[key] = sub(buffer, pos + 1, new_pos) 182 | return new_pos 183 | end 184 | end 185 | end 186 | 187 | function BytesDecoder(field_number, is_repeated, is_packed, key, new_default) 188 | local DecodeVarint = _DecodeVarint 189 | local sub = string.sub 190 | assert(not is_packed) 191 | if is_repeated then 192 | local tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 193 | local tag_len = #tag_bytes 194 | return function (buffer, pos, pend, message, field_dict) 195 | local value = field_dict[key] 196 | if value == nil then 197 | value = new_default(message) 198 | field_dict[key] = value 199 | end 200 | while 1 do 201 | local size, new_pos 202 | size, pos = DecodeVarint(buffer, pos) 203 | new_pos = pos + size 204 | if new_pos > pend then 205 | error('Truncated string.') 206 | end 207 | value:append(sub(buffer, pos + 1, new_pos)) 208 | pos = new_pos + tag_len 209 | if sub(buffer, new_pos + 1, pos) ~= tag_bytes or new_pos == pend then 210 | return new_pos 211 | end 212 | end 213 | end 214 | else 215 | return function(buffer, pos, pend, message, field_dict) 216 | local size, new_pos 217 | size, pos = DecodeVarint(buffer, pos) 218 | new_pos = pos + size 219 | if new_pos > pend then 220 | error('Truncated string.') 221 | end 222 | field_dict[key] = sub(buffer, pos + 1, new_pos) 223 | return new_pos 224 | end 225 | end 226 | end 227 | 228 | function MessageDecoder(field_number, is_repeated, is_packed, key, new_default) 229 | local DecodeVarint = _DecodeVarint 230 | local sub = string.sub 231 | 232 | assert(not is_packed) 233 | if is_repeated then 234 | local tag_bytes = encoder.TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 235 | local tag_len = #tag_bytes 236 | return function (buffer, pos, pend, message, field_dict) 237 | local value = field_dict[key] 238 | if value == nil then 239 | value = new_default(message) 240 | field_dict[key] = value 241 | end 242 | while 1 do 243 | local size, new_pos 244 | size, pos = DecodeVarint(buffer, pos) 245 | new_pos = pos + size 246 | if new_pos > pend then 247 | error('Truncated message.') 248 | end 249 | if value:add():_InternalParse(buffer, pos, new_pos) ~= new_pos then 250 | error('Unexpected end-group tag.') 251 | end 252 | pos = new_pos + tag_len 253 | if sub(buffer, new_pos + 1, pos) ~= tag_bytes or new_pos == pend then 254 | return new_pos 255 | end 256 | end 257 | end 258 | else 259 | return function (buffer, pos, pend, message, field_dict) 260 | local value = field_dict[key] 261 | if value == nil then 262 | value = new_default(message) 263 | field_dict[key] = value 264 | end 265 | local size, new_pos 266 | size, pos = DecodeVarint(buffer, pos) 267 | new_pos = pos + size 268 | if new_pos > pend then 269 | error('Truncated message.') 270 | end 271 | if value:_InternalParse(buffer, pos, new_pos) ~= new_pos then 272 | error('Unexpected end-group tag.') 273 | end 274 | return new_pos 275 | end 276 | end 277 | end 278 | 279 | function _SkipVarint(buffer, pos, pend) 280 | local value 281 | value, pos = _DecodeVarint(buffer, pos) 282 | return pos 283 | end 284 | 285 | function _SkipFixed64(buffer, pos, pend) 286 | pos = pos + 8 287 | if pos > pend then 288 | error('Truncated message.') 289 | end 290 | return pos 291 | end 292 | 293 | function _SkipLengthDelimited(buffer, pos, pend) 294 | local size 295 | size, pos = _DecodeVarint(buffer, pos) 296 | pos = pos + size 297 | if pos > pend then 298 | error('Truncated message.') 299 | end 300 | return pos 301 | end 302 | 303 | function _SkipFixed32(buffer, pos, pend) 304 | pos = pos + 4 305 | if pos > pend then 306 | error('Truncated message.') 307 | end 308 | return pos 309 | end 310 | 311 | function _RaiseInvalidWireType(buffer, pos, pend) 312 | error('Tag had invalid wire type.') 313 | end 314 | 315 | function _FieldSkipper() 316 | WIRETYPE_TO_SKIPPER = { 317 | _SkipVarint, 318 | _SkipFixed64, 319 | _SkipLengthDelimited, 320 | _SkipGroup, 321 | _EndGroup, 322 | _SkipFixed32, 323 | _RaiseInvalidWireType, 324 | _RaiseInvalidWireType, 325 | } 326 | 327 | -- wiretype_mask = wire_format.TAG_TYPE_MASK 328 | local ord = string.byte 329 | local sub = string.sub 330 | 331 | return function (buffer, pos, pend, tag_bytes) 332 | local wire_type = ord(sub(tag_bytes, 1, 1)) % 8 + 1 333 | return WIRETYPE_TO_SKIPPER[wire_type](buffer, pos, pend) 334 | end 335 | end 336 | 337 | SkipField = _FieldSkipper() 338 | -------------------------------------------------------------------------------- /protobuf/pb.c: -------------------------------------------------------------------------------- 1 | /* 2 | * ===================================================================================== 3 | * 4 | * Filename: pb.c 5 | * 6 | * Description: protoc-gen-lua 7 | * Google's Protocol Buffers project, ported to lua. 8 | * https://code.google.com/p/protoc-gen-lua/ 9 | * 10 | * Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 11 | * All rights reserved. 12 | * 13 | * Use, modification and distribution are subject to the "New BSD License" 14 | * as listed at . 15 | * 16 | * Created: 2010年08月02日 18时04分21秒 17 | * 18 | * Company: NetEase 19 | * 20 | * ===================================================================================== 21 | */ 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef _ALLBSD_SOURCE 30 | #include 31 | #else 32 | #include 33 | #endif 34 | 35 | #if __BYTE_ORDER == __LITTLE_ENDIAN 36 | #define IS_LITTLE_ENDIAN 37 | #endif 38 | 39 | #define IOSTRING_META "protobuf.IOString" 40 | 41 | #define checkiostring(L) \ 42 | (IOString*) luaL_checkudata(L, 1, IOSTRING_META) 43 | 44 | #define IOSTRING_BUF_LEN 65535 45 | 46 | typedef struct{ 47 | size_t size; 48 | char buf[IOSTRING_BUF_LEN]; 49 | } IOString; 50 | 51 | static void pack_varint(luaL_Buffer *b, uint64_t value) 52 | { 53 | if (value >= 0x80) 54 | { 55 | luaL_addchar(b, value | 0x80); 56 | value >>= 7; 57 | if (value >= 0x80) 58 | { 59 | luaL_addchar(b, value | 0x80); 60 | value >>= 7; 61 | if (value >= 0x80) 62 | { 63 | luaL_addchar(b, value | 0x80); 64 | value >>= 7; 65 | if (value >= 0x80) 66 | { 67 | luaL_addchar(b, value | 0x80); 68 | value >>= 7; 69 | if (value >= 0x80) 70 | { 71 | luaL_addchar(b, value | 0x80); 72 | value >>= 7; 73 | if (value >= 0x80) 74 | { 75 | luaL_addchar(b, value | 0x80); 76 | value >>= 7; 77 | if (value >= 0x80) 78 | { 79 | luaL_addchar(b, value | 0x80); 80 | value >>= 7; 81 | if (value >= 0x80) 82 | { 83 | luaL_addchar(b, value | 0x80); 84 | value >>= 7; 85 | if (value >= 0x80) 86 | { 87 | luaL_addchar(b, value | 0x80); 88 | value >>= 7; 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | luaL_addchar(b, value); 99 | } 100 | 101 | static int varint_encoder(lua_State *L) 102 | { 103 | lua_Number l_value = luaL_checknumber(L, 2); 104 | uint64_t value = (uint64_t)l_value; 105 | 106 | luaL_Buffer b; 107 | luaL_buffinit(L, &b); 108 | 109 | pack_varint(&b, value); 110 | 111 | lua_settop(L, 1); 112 | luaL_pushresult(&b); 113 | lua_call(L, 1, 0); 114 | return 0; 115 | } 116 | 117 | static int signed_varint_encoder(lua_State *L) 118 | { 119 | lua_Number l_value = luaL_checknumber(L, 2); 120 | int64_t value = (int64_t)l_value; 121 | 122 | luaL_Buffer b; 123 | luaL_buffinit(L, &b); 124 | 125 | if (value < 0) 126 | { 127 | pack_varint(&b, *(uint64_t*)&value); 128 | }else{ 129 | pack_varint(&b, value); 130 | } 131 | 132 | lua_settop(L, 1); 133 | luaL_pushresult(&b); 134 | lua_call(L, 1, 0); 135 | return 0; 136 | } 137 | 138 | static int pack_fixed32(lua_State *L, uint8_t* value){ 139 | #ifdef IS_LITTLE_ENDIAN 140 | lua_pushlstring(L, (char*)value, 4); 141 | #else 142 | uint32_t v = htole32(*(uint32_t*)value); 143 | lua_pushlstring(L, (char*)&v, 4); 144 | #endif 145 | return 0; 146 | } 147 | 148 | static int pack_fixed64(lua_State *L, uint8_t* value){ 149 | #ifdef IS_LITTLE_ENDIAN 150 | lua_pushlstring(L, (char*)value, 8); 151 | #else 152 | uint64_t v = htole64(*(uint64_t*)value); 153 | lua_pushlstring(L, (char*)&v, 8); 154 | #endif 155 | return 0; 156 | } 157 | 158 | static int struct_pack(lua_State *L) 159 | { 160 | uint8_t format = luaL_checkinteger(L, 2); 161 | lua_Number value = luaL_checknumber(L, 3); 162 | lua_settop(L, 1); 163 | 164 | switch(format){ 165 | case 'i': 166 | { 167 | int32_t v = (int32_t)value; 168 | pack_fixed32(L, (uint8_t*)&v); 169 | break; 170 | } 171 | case 'q': 172 | { 173 | int64_t v = (int64_t)value; 174 | pack_fixed64(L, (uint8_t*)&v); 175 | break; 176 | } 177 | case 'f': 178 | { 179 | float v = (float)value; 180 | pack_fixed32(L, (uint8_t*)&v); 181 | break; 182 | } 183 | case 'd': 184 | { 185 | double v = (double)value; 186 | pack_fixed64(L, (uint8_t*)&v); 187 | break; 188 | } 189 | case 'I': 190 | { 191 | uint32_t v = (uint32_t)value; 192 | pack_fixed32(L, (uint8_t*)&v); 193 | break; 194 | } 195 | case 'Q': 196 | { 197 | uint64_t v = (uint64_t) value; 198 | pack_fixed64(L, (uint8_t*)&v); 199 | break; 200 | } 201 | default: 202 | luaL_error(L, "Unknown, format"); 203 | } 204 | lua_call(L, 1, 0); 205 | return 0; 206 | } 207 | 208 | static size_t size_varint(const char* buffer, size_t len) 209 | { 210 | size_t pos = 0; 211 | while(buffer[pos] & 0x80){ 212 | ++pos; 213 | if(pos > len){ 214 | return -1; 215 | } 216 | } 217 | return pos+1; 218 | } 219 | 220 | static uint64_t unpack_varint(const char* buffer, size_t len) 221 | { 222 | uint64_t value = buffer[0] & 0x7f; 223 | size_t shift = 7; 224 | size_t pos=0; 225 | for(pos = 1; pos < len; ++pos) 226 | { 227 | value |= ((uint64_t)(buffer[pos] & 0x7f)) << shift; 228 | shift += 7; 229 | } 230 | return value; 231 | } 232 | 233 | static int varint_decoder(lua_State *L) 234 | { 235 | size_t len; 236 | const char* buffer = luaL_checklstring(L, 1, &len); 237 | size_t pos = luaL_checkinteger(L, 2); 238 | 239 | buffer += pos; 240 | len = size_varint(buffer, len); 241 | if(len == -1){ 242 | luaL_error(L, "error data %s, len:%d", buffer, len); 243 | }else{ 244 | lua_pushnumber(L, (lua_Number)unpack_varint(buffer, len)); 245 | lua_pushinteger(L, len + pos); 246 | } 247 | return 2; 248 | } 249 | 250 | static int signed_varint_decoder(lua_State *L) 251 | { 252 | size_t len; 253 | const char* buffer = luaL_checklstring(L, 1, &len); 254 | size_t pos = luaL_checkinteger(L, 2); 255 | buffer += pos; 256 | len = size_varint(buffer, len); 257 | 258 | if(len == -1){ 259 | luaL_error(L, "error data %s, len:%d", buffer, len); 260 | }else{ 261 | lua_pushnumber(L, (lua_Number)(int64_t)unpack_varint(buffer, len)); 262 | lua_pushinteger(L, len + pos); 263 | } 264 | return 2; 265 | } 266 | 267 | static int zig_zag_encode32(lua_State *L) 268 | { 269 | int32_t n = luaL_checkinteger(L, 1); 270 | uint32_t value = (n << 1) ^ (n >> 31); 271 | lua_pushinteger(L, value); 272 | return 1; 273 | } 274 | 275 | static int zig_zag_decode32(lua_State *L) 276 | { 277 | uint32_t n = (uint32_t)luaL_checkinteger(L, 1); 278 | int32_t value = (n >> 1) ^ - (int32_t)(n & 1); 279 | lua_pushinteger(L, value); 280 | return 1; 281 | } 282 | 283 | static int zig_zag_encode64(lua_State *L) 284 | { 285 | int64_t n = (int64_t)luaL_checknumber(L, 1); 286 | uint64_t value = (n << 1) ^ (n >> 63); 287 | lua_pushinteger(L, value); 288 | return 1; 289 | } 290 | 291 | static int zig_zag_decode64(lua_State *L) 292 | { 293 | uint64_t n = (uint64_t)luaL_checknumber(L, 1); 294 | int64_t value = (n >> 1) ^ - (int64_t)(n & 1); 295 | lua_pushinteger(L, value); 296 | return 1; 297 | } 298 | 299 | static int read_tag(lua_State *L) 300 | { 301 | size_t len; 302 | const char* buffer = luaL_checklstring(L, 1, &len); 303 | size_t pos = luaL_checkinteger(L, 2); 304 | 305 | buffer += pos; 306 | len = size_varint(buffer, len); 307 | if(len == -1){ 308 | luaL_error(L, "error data %s, len:%d", buffer, len); 309 | }else{ 310 | lua_pushlstring(L, buffer, len); 311 | lua_pushinteger(L, len + pos); 312 | } 313 | return 2; 314 | } 315 | 316 | static const uint8_t* unpack_fixed32(const uint8_t* buffer, uint8_t* cache) 317 | { 318 | #ifdef IS_LITTLE_ENDIAN 319 | return buffer; 320 | #else 321 | *(uint32_t*)cache = le32toh(*(uint32_t*)buffer); 322 | return cache; 323 | #endif 324 | } 325 | 326 | static const uint8_t* unpack_fixed64(const uint8_t* buffer, uint8_t* cache) 327 | { 328 | #ifdef IS_LITTLE_ENDIAN 329 | return buffer; 330 | #else 331 | *(uint64_t*)cache = le64toh(*(uint64_t*)buffer); 332 | return cache; 333 | #endif 334 | } 335 | 336 | static int struct_unpack(lua_State *L) 337 | { 338 | uint8_t format = luaL_checkinteger(L, 1); 339 | size_t len; 340 | const uint8_t* buffer = (uint8_t*)luaL_checklstring(L, 2, &len); 341 | size_t pos = luaL_checkinteger(L, 3); 342 | 343 | buffer += pos; 344 | uint8_t out[8]; 345 | switch(format){ 346 | case 'i': 347 | { 348 | lua_pushinteger(L, *(int32_t*)unpack_fixed32(buffer, out)); 349 | break; 350 | } 351 | case 'q': 352 | { 353 | lua_pushnumber(L, (lua_Number)*(int64_t*)unpack_fixed64(buffer, out)); 354 | break; 355 | } 356 | case 'f': 357 | { 358 | lua_pushnumber(L, (lua_Number)*(float*)unpack_fixed32(buffer, out)); 359 | break; 360 | } 361 | case 'd': 362 | { 363 | lua_pushnumber(L, (lua_Number)*(double*)unpack_fixed64(buffer, out)); 364 | break; 365 | } 366 | case 'I': 367 | { 368 | lua_pushnumber(L, *(uint32_t*)unpack_fixed32(buffer, out)); 369 | break; 370 | } 371 | case 'Q': 372 | { 373 | lua_pushnumber(L, (lua_Number)*(uint64_t*)unpack_fixed64(buffer, out)); 374 | break; 375 | } 376 | default: 377 | luaL_error(L, "Unknown, format"); 378 | } 379 | return 1; 380 | } 381 | 382 | static int iostring_new(lua_State* L) 383 | { 384 | IOString* io = (IOString*)lua_newuserdata(L, sizeof(IOString)); 385 | io->size = 0; 386 | 387 | luaL_getmetatable(L, IOSTRING_META); 388 | lua_setmetatable(L, -2); 389 | return 1; 390 | } 391 | 392 | static int iostring_str(lua_State* L) 393 | { 394 | IOString *io = checkiostring(L); 395 | lua_pushlstring(L, io->buf, io->size); 396 | return 1; 397 | } 398 | 399 | static int iostring_len(lua_State* L) 400 | { 401 | IOString *io = checkiostring(L); 402 | lua_pushinteger(L, io->size); 403 | return 1; 404 | } 405 | 406 | static int iostring_write(lua_State* L) 407 | { 408 | IOString *io = checkiostring(L); 409 | size_t size; 410 | const char* str = luaL_checklstring(L, 2, &size); 411 | if(io->size + size > IOSTRING_BUF_LEN){ 412 | luaL_error(L, "Out of range"); 413 | } 414 | memcpy(io->buf + io->size, str, size); 415 | io->size += size; 416 | return 0; 417 | } 418 | 419 | static int iostring_sub(lua_State* L) 420 | { 421 | IOString *io = checkiostring(L); 422 | size_t begin = luaL_checkinteger(L, 2); 423 | size_t end = luaL_checkinteger(L, 3); 424 | 425 | if(begin > end || end > io->size) 426 | { 427 | luaL_error(L, "Out of range"); 428 | } 429 | lua_pushlstring(L, io->buf + begin - 1, end - begin + 1); 430 | return 1; 431 | } 432 | 433 | static int iostring_clear(lua_State* L) 434 | { 435 | IOString *io = checkiostring(L); 436 | io->size = 0; 437 | return 0; 438 | } 439 | 440 | static const struct luaL_reg _pb [] = { 441 | {"varint_encoder", varint_encoder}, 442 | {"signed_varint_encoder", signed_varint_encoder}, 443 | {"read_tag", read_tag}, 444 | {"struct_pack", struct_pack}, 445 | {"struct_unpack", struct_unpack}, 446 | {"varint_decoder", varint_decoder}, 447 | {"signed_varint_decoder", signed_varint_decoder}, 448 | {"zig_zag_decode32", zig_zag_decode32}, 449 | {"zig_zag_encode32", zig_zag_encode32}, 450 | {"zig_zag_decode64", zig_zag_decode64}, 451 | {"zig_zag_encode64", zig_zag_encode64}, 452 | {"new_iostring", iostring_new}, 453 | {NULL, NULL} 454 | }; 455 | 456 | static const struct luaL_reg _c_iostring_m [] = { 457 | {"__tostring", iostring_str}, 458 | {"__len", iostring_len}, 459 | {"write", iostring_write}, 460 | {"sub", iostring_sub}, 461 | {"clear", iostring_clear}, 462 | {NULL, NULL} 463 | }; 464 | 465 | int luaopen_pb (lua_State *L) 466 | { 467 | luaL_newmetatable(L, IOSTRING_META); 468 | lua_pushvalue(L, -1); 469 | lua_setfield(L, -2, "__index"); 470 | luaL_register(L, NULL, _c_iostring_m); 471 | 472 | luaL_register(L, "pb", _pb); 473 | return 1; 474 | } 475 | -------------------------------------------------------------------------------- /plugin/protoc-gen-lua: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- encoding:utf8 -*- 3 | # protoc-gen-erl 4 | # Google's Protocol Buffers project, ported to lua. 5 | # https://code.google.com/p/protoc-gen-lua/ 6 | # 7 | # Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 8 | # All rights reserved. 9 | # 10 | # Use, modification and distribution are subject to the "New BSD License" 11 | # as listed at . 12 | 13 | import sys 14 | import os.path as path 15 | from cStringIO import StringIO 16 | 17 | import plugin_pb2 18 | import google.protobuf.descriptor_pb2 as descriptor_pb2 19 | 20 | _packages = {} 21 | _files = {} 22 | _message = {} 23 | 24 | FDP = plugin_pb2.descriptor_pb2.FieldDescriptorProto 25 | 26 | if sys.platform == "win32": 27 | import msvcrt, os 28 | msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY) 29 | msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) 30 | 31 | class CppType: 32 | CPPTYPE_INT32 = 1 33 | CPPTYPE_INT64 = 2 34 | CPPTYPE_UINT32 = 3 35 | CPPTYPE_UINT64 = 4 36 | CPPTYPE_DOUBLE = 5 37 | CPPTYPE_FLOAT = 6 38 | CPPTYPE_BOOL = 7 39 | CPPTYPE_ENUM = 8 40 | CPPTYPE_STRING = 9 41 | CPPTYPE_MESSAGE = 10 42 | 43 | CPP_TYPE ={ 44 | FDP.TYPE_DOUBLE : CppType.CPPTYPE_DOUBLE, 45 | FDP.TYPE_FLOAT : CppType.CPPTYPE_FLOAT, 46 | FDP.TYPE_INT64 : CppType.CPPTYPE_INT64, 47 | FDP.TYPE_UINT64 : CppType.CPPTYPE_UINT64, 48 | FDP.TYPE_INT32 : CppType.CPPTYPE_INT32, 49 | FDP.TYPE_FIXED64 : CppType.CPPTYPE_UINT64, 50 | FDP.TYPE_FIXED32 : CppType.CPPTYPE_UINT32, 51 | FDP.TYPE_BOOL : CppType.CPPTYPE_BOOL, 52 | FDP.TYPE_STRING : CppType.CPPTYPE_STRING, 53 | FDP.TYPE_MESSAGE : CppType.CPPTYPE_MESSAGE, 54 | FDP.TYPE_BYTES : CppType.CPPTYPE_STRING, 55 | FDP.TYPE_UINT32 : CppType.CPPTYPE_UINT32, 56 | FDP.TYPE_ENUM : CppType.CPPTYPE_ENUM, 57 | FDP.TYPE_SFIXED32 : CppType.CPPTYPE_INT32, 58 | FDP.TYPE_SFIXED64 : CppType.CPPTYPE_INT64, 59 | FDP.TYPE_SINT32 : CppType.CPPTYPE_INT32, 60 | FDP.TYPE_SINT64 : CppType.CPPTYPE_INT64 61 | } 62 | 63 | def printerr(*args): 64 | sys.stderr.write(" ".join(args)) 65 | sys.stderr.write("\n") 66 | sys.stderr.flush() 67 | 68 | class TreeNode(object): 69 | def __init__(self, name, parent=None, filename=None, package=None): 70 | super(TreeNode, self).__init__() 71 | self.child = [] 72 | self.parent = parent 73 | self.filename = filename 74 | self.package = package 75 | if parent: 76 | self.parent.add_child(self) 77 | self.name = name 78 | 79 | def add_child(self, child): 80 | self.child.append(child) 81 | 82 | def find_child(self, child_names): 83 | if child_names: 84 | for i in self.child: 85 | if i.name == child_names[0]: 86 | return i.find_child(child_names[1:]) 87 | raise StandardError 88 | else: 89 | return self 90 | 91 | def get_child(self, child_name): 92 | for i in self.child: 93 | if i.name == child_name: 94 | return i 95 | return None 96 | 97 | def get_path(self, end = None): 98 | pos = self 99 | out = [] 100 | while pos and pos != end: 101 | out.append(pos.name) 102 | pos = pos.parent 103 | out.reverse() 104 | return '.'.join(out) 105 | 106 | def get_global_name(self): 107 | return self.get_path() 108 | 109 | def get_local_name(self): 110 | pos = self 111 | while pos.parent: 112 | pos = pos.parent 113 | if self.package and pos.name == self.package[-1]: 114 | break 115 | return self.get_path(pos) 116 | 117 | def __str__(self): 118 | return self.to_string(0) 119 | 120 | def __repr__(self): 121 | return str(self) 122 | 123 | def to_string(self, indent = 0): 124 | return ' '*indent + '\n' 127 | 128 | class Env(object): 129 | filename = None 130 | package = None 131 | extend = None 132 | descriptor = None 133 | message = None 134 | context = None 135 | register = None 136 | def __init__(self): 137 | self.message_tree = TreeNode('') 138 | self.scope = self.message_tree 139 | 140 | def get_global_name(self): 141 | return self.scope.get_global_name() 142 | 143 | def get_local_name(self): 144 | return self.scope.get_local_name() 145 | 146 | def get_ref_name(self, type_name): 147 | try: 148 | node = self.lookup_name(type_name) 149 | except: 150 | # if the child doesn't be founded, it must be in this file 151 | return type_name[len('.'.join(self.package)) + 1:] 152 | if node.filename != self.filename: 153 | return node.filename + '_pb.' + node.get_local_name() 154 | return node.get_local_name() 155 | 156 | def lookup_name(self, name): 157 | names = name.split('.') 158 | if names[0] == '': 159 | return self.message_tree.find_child(names[1:]) 160 | else: 161 | return self.scope.parent.find_child(names) 162 | 163 | def enter_package(self, package): 164 | if not package: 165 | return self.message_tree 166 | names = package.split('.') 167 | pos = self.message_tree 168 | for i, name in enumerate(names): 169 | new_pos = pos.get_child(name) 170 | if new_pos: 171 | pos = new_pos 172 | else: 173 | return self._build_nodes(pos, names[i:]) 174 | return pos 175 | 176 | def enter_file(self, filename, package): 177 | self.filename = filename 178 | self.package = package.split('.') 179 | self._init_field() 180 | self.scope = self.enter_package(package) 181 | 182 | def exit_file(self): 183 | self._init_field() 184 | self.filename = None 185 | self.package = [] 186 | self.scope = self.scope.parent 187 | 188 | def enter(self, message_name): 189 | self.scope = TreeNode(message_name, self.scope, self.filename, 190 | self.package) 191 | 192 | def exit(self): 193 | self.scope = self.scope.parent 194 | 195 | def _init_field(self): 196 | self.descriptor = [] 197 | self.context = [] 198 | self.message = [] 199 | self.register = [] 200 | 201 | def _build_nodes(self, node, names): 202 | parent = node 203 | for i in names: 204 | parent = TreeNode(i, parent, self.filename, self.package) 205 | return parent 206 | 207 | class Writer(object): 208 | def __init__(self, prefix=None): 209 | self.io = StringIO() 210 | self.__indent = '' 211 | self.__prefix = prefix 212 | 213 | def getvalue(self): 214 | return self.io.getvalue() 215 | 216 | def __enter__(self): 217 | self.__indent += ' ' 218 | return self 219 | 220 | def __exit__(self, type, value, trackback): 221 | self.__indent = self.__indent[:-4] 222 | 223 | def __call__(self, data): 224 | self.io.write(self.__indent) 225 | if self.__prefix: 226 | self.io.write(self.__prefix) 227 | self.io.write(data) 228 | 229 | DEFAULT_VALUE = { 230 | FDP.TYPE_DOUBLE : '0.0', 231 | FDP.TYPE_FLOAT : '0.0', 232 | FDP.TYPE_INT64 : '0', 233 | FDP.TYPE_UINT64 : '0', 234 | FDP.TYPE_INT32 : '0', 235 | FDP.TYPE_FIXED64 : '0', 236 | FDP.TYPE_FIXED32 : '0', 237 | FDP.TYPE_BOOL : 'false', 238 | FDP.TYPE_STRING : '""', 239 | FDP.TYPE_MESSAGE : 'nil', 240 | FDP.TYPE_BYTES : '""', 241 | FDP.TYPE_UINT32 : '0', 242 | FDP.TYPE_ENUM : '1', 243 | FDP.TYPE_SFIXED32 : '0', 244 | FDP.TYPE_SFIXED64 : '0', 245 | FDP.TYPE_SINT32 : '0', 246 | FDP.TYPE_SINT64 : '0', 247 | } 248 | 249 | def code_gen_enum_item(index, enum_value, env): 250 | full_name = env.get_local_name() + '.' + enum_value.name 251 | obj_name = full_name.upper().replace('.', '_') + '_ENUM' 252 | env.descriptor.append( 253 | "local %s = protobuf.EnumValueDescriptor();\n"% obj_name 254 | ) 255 | 256 | context = Writer(obj_name) 257 | context('.name = "%s"\n' % enum_value.name) 258 | context('.index = %d\n' % index) 259 | context('.number = %d\n' % enum_value.number) 260 | 261 | env.context.append(context.getvalue()) 262 | return obj_name 263 | 264 | def code_gen_enum(enum_desc, env): 265 | env.enter(enum_desc.name) 266 | full_name = env.get_local_name() 267 | obj_name = full_name.upper().replace('.', '_') 268 | env.descriptor.append( 269 | "local %s = protobuf.EnumDescriptor();\n"% obj_name 270 | ) 271 | 272 | context = Writer(obj_name) 273 | context('.name = "%s"\n' % enum_desc.name) 274 | context('.full_name = "%s"\n' % env.get_global_name()) 275 | 276 | values = [] 277 | for i, enum_value in enumerate(enum_desc.value): 278 | values.append(code_gen_enum_item(i, enum_value, env)) 279 | context('.values = {%s}\n' % ','.join(values)) 280 | 281 | env.context.append(context.getvalue()) 282 | env.exit() 283 | return obj_name 284 | 285 | def code_gen_field(index, field_desc, env): 286 | full_name = env.get_local_name() + '.' + field_desc.name 287 | obj_name = full_name.upper().replace('.', '_') + '_FIELD' 288 | env.descriptor.append( 289 | "local %s = protobuf.FieldDescriptor();\n"% obj_name 290 | ) 291 | 292 | context = Writer(obj_name) 293 | 294 | context('.name = "%s"\n' % field_desc.name) 295 | context('.full_name = "%s"\n' % ( 296 | env.get_global_name() + '.' + field_desc.name)) 297 | context('.number = %d\n' % field_desc.number) 298 | context('.index = %d\n' % index) 299 | context('.label = %d\n' % field_desc.label) 300 | 301 | if field_desc.HasField("default_value"): 302 | context('.has_default_value = true\n') 303 | value = field_desc.default_value 304 | if field_desc.type == FDP.TYPE_STRING: 305 | context('.default_value = "%s"\n'%value) 306 | else: 307 | context('.default_value = %s\n'%value) 308 | else: 309 | context('.has_default_value = false\n') 310 | if field_desc.label == FDP.LABEL_REPEATED: 311 | default_value = "{}" 312 | elif field_desc.HasField('type_name'): 313 | default_value = "nil" 314 | else: 315 | default_value = DEFAULT_VALUE[field_desc.type] 316 | context('.default_value = %s\n' % default_value) 317 | 318 | if field_desc.HasField('type_name'): 319 | type_name = env.get_ref_name(field_desc.type_name).upper().replace('.', '_') 320 | if field_desc.type == FDP.TYPE_MESSAGE: 321 | context('.message_type = %s\n' % type_name) 322 | else: 323 | context('.enum_type = %s\n' % type_name) 324 | 325 | if field_desc.HasField('extendee'): 326 | type_name = env.get_ref_name(field_desc.extendee) 327 | env.register.append( 328 | "%s.RegisterExtension(%s)\n" % (type_name, obj_name) 329 | ) 330 | 331 | context('.type = %d\n' % field_desc.type) 332 | context('.cpp_type = %d\n\n' % CPP_TYPE[field_desc.type]) 333 | env.context.append(context.getvalue()) 334 | return obj_name 335 | 336 | def code_gen_message(message_descriptor, env, containing_type = None): 337 | env.enter(message_descriptor.name) 338 | full_name = env.get_local_name() 339 | obj_name = full_name.upper().replace('.', '_') 340 | env.descriptor.append( 341 | "local %s = protobuf.Descriptor();\n"% obj_name 342 | ) 343 | 344 | context = Writer(obj_name) 345 | context('.name = "%s"\n' % message_descriptor.name) 346 | context('.full_name = "%s"\n' % env.get_global_name()) 347 | 348 | nested_types = [] 349 | for msg_desc in message_descriptor.nested_type: 350 | msg_name = code_gen_message(msg_desc, env, obj_name) 351 | nested_types.append(msg_name) 352 | context('.nested_types = {%s}\n' % ', '.join(nested_types)) 353 | 354 | enums = [] 355 | for enum_desc in message_descriptor.enum_type: 356 | enums.append(code_gen_enum(enum_desc, env)) 357 | context('.enum_types = {%s}\n' % ', '.join(enums)) 358 | 359 | fields = [] 360 | for i, field_desc in enumerate(message_descriptor.field): 361 | fields.append(code_gen_field(i, field_desc, env)) 362 | 363 | context('.fields = {%s}\n' % ', '.join(fields)) 364 | if len(message_descriptor.extension_range) > 0: 365 | context('.is_extendable = true\n') 366 | else: 367 | context('.is_extendable = false\n') 368 | 369 | extensions = [] 370 | for i, field_desc in enumerate(message_descriptor.extension): 371 | extensions.append(code_gen_field(i, field_desc, env)) 372 | context('.extensions = {%s}\n' % ', '.join(extensions)) 373 | 374 | if containing_type: 375 | context('.containing_type = %s\n' % containing_type) 376 | 377 | env.message.append('%s = protobuf.Message(%s)\n' % (full_name, 378 | obj_name)) 379 | 380 | env.context.append(context.getvalue()) 381 | env.exit() 382 | return obj_name 383 | 384 | def write_header(writer): 385 | writer("""-- Generated By protoc-gen-lua Do not Edit 386 | """) 387 | 388 | def code_gen_file(proto_file, env, is_gen): 389 | filename = path.splitext(proto_file.name)[0] 390 | env.enter_file(filename, proto_file.package) 391 | 392 | includes = [] 393 | for f in proto_file.dependency: 394 | inc_file = path.splitext(f)[0] 395 | includes.append(inc_file) 396 | 397 | # for field_desc in proto_file.extension: 398 | # code_gen_extensions(field_desc, field_desc.name, env) 399 | 400 | for enum_desc in proto_file.enum_type: 401 | code_gen_enum(enum_desc, env) 402 | for enum_value in enum_desc.value: 403 | env.message.append('%s = %d\n' % (enum_value.name, 404 | enum_value.number)) 405 | 406 | for msg_desc in proto_file.message_type: 407 | code_gen_message(msg_desc, env) 408 | 409 | if is_gen: 410 | lua = Writer() 411 | write_header(lua) 412 | lua('local protobuf = require "protobuf"\n') 413 | for i in includes: 414 | lua('local %s_pb = require("%s_pb")\n' % (i, i)) 415 | lua("module('%s_pb')\n" % env.filename) 416 | 417 | lua('\n\n') 418 | map(lua, env.descriptor) 419 | lua('\n') 420 | map(lua, env.context) 421 | lua('\n') 422 | env.message.sort() 423 | map(lua, env.message) 424 | lua('\n') 425 | map(lua, env.register) 426 | 427 | _files[env.filename+ '_pb.lua'] = lua.getvalue() 428 | env.exit_file() 429 | 430 | def main(): 431 | plugin_require_bin = sys.stdin.read() 432 | code_gen_req = plugin_pb2.CodeGeneratorRequest() 433 | code_gen_req.ParseFromString(plugin_require_bin) 434 | 435 | env = Env() 436 | for proto_file in code_gen_req.proto_file: 437 | code_gen_file(proto_file, env, 438 | proto_file.name in code_gen_req.file_to_generate) 439 | 440 | code_generated = plugin_pb2.CodeGeneratorResponse() 441 | for k in _files: 442 | file_desc = code_generated.file.add() 443 | file_desc.name = k 444 | file_desc.content = _files[k] 445 | 446 | sys.stdout.write(code_generated.SerializeToString()) 447 | 448 | if __name__ == "__main__": 449 | main() 450 | 451 | -------------------------------------------------------------------------------- /protobuf/encoder.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: encoder.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年07月29日 19时30分46秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | local string = string 19 | local table = table 20 | local ipairs = ipairs 21 | local assert =assert 22 | 23 | local pb = require "pb" 24 | local wire_format = require "wire_format" 25 | module "encoder" 26 | 27 | function _VarintSize(value) 28 | if value <= 0x7f then return 1 end 29 | if value <= 0x3fff then return 2 end 30 | if value <= 0x1fffff then return 3 end 31 | if value <= 0xfffffff then return 4 end 32 | return 5 33 | end 34 | 35 | function _SignedVarintSize(value) 36 | if value < 0 then return 10 end 37 | if value <= 0x7f then return 1 end 38 | if value <= 0x3fff then return 2 end 39 | if value <= 0x1fffff then return 3 end 40 | if value <= 0xfffffff then return 4 end 41 | return 5 42 | end 43 | 44 | function _TagSize(field_number) 45 | return _VarintSize(wire_format.PackTag(field_number, 0)) 46 | end 47 | 48 | function _SimpleSizer(compute_value_size) 49 | return function(field_number, is_repeated, is_packed) 50 | local tag_size = _TagSize(field_number) 51 | if is_packed then 52 | local VarintSize = _VarintSize 53 | return function(value) 54 | local result = 0 55 | for _, element in ipairs(value) do 56 | result = result + compute_value_size(element) 57 | end 58 | return result + VarintSize(result) + tag_size 59 | end 60 | elseif is_repeated then 61 | return function(value) 62 | local result = tag_size * #value 63 | for _, element in ipairs(value) do 64 | result = result + compute_value_size(element) 65 | end 66 | return result 67 | end 68 | else 69 | return function (value) 70 | return tag_size + compute_value_size(value) 71 | end 72 | end 73 | end 74 | end 75 | 76 | function _ModifiedSizer(compute_value_size, modify_value) 77 | return function (field_number, is_repeated, is_packed) 78 | local tag_size = _TagSize(field_number) 79 | if is_packed then 80 | local VarintSize = _VarintSize 81 | return function (value) 82 | local result = 0 83 | for _, element in ipairs(value) do 84 | result = result + compute_value_size(modify_value(element)) 85 | end 86 | return result + VarintSize(result) + tag_size 87 | end 88 | elseif is_repeated then 89 | return function (value) 90 | local result = tag_size * #value 91 | for _, element in ipairs(value) do 92 | result = result + compute_value_size(modify_value(element)) 93 | end 94 | return result 95 | end 96 | else 97 | return function (value) 98 | return tag_size + compute_value_size(modify_value(value)) 99 | end 100 | end 101 | end 102 | end 103 | 104 | function _FixedSizer(value_size) 105 | return function (field_number, is_repeated, is_packed) 106 | local tag_size = _TagSize(field_number) 107 | if is_packed then 108 | local VarintSize = _VarintSize 109 | return function (value) 110 | local result = #value * value_size 111 | return result + VarintSize(result) + tag_size 112 | end 113 | elseif is_repeated then 114 | local element_size = value_size + tag_size 115 | return function(value) 116 | return #value * element_size 117 | end 118 | else 119 | local field_size = value_size + tag_size 120 | return function (value) 121 | return field_size 122 | end 123 | end 124 | end 125 | end 126 | 127 | Int32Sizer = _SimpleSizer(_SignedVarintSize) 128 | Int64Sizer = Int32Sizer 129 | EnumSizer = Int32Sizer 130 | 131 | UInt32Sizer = _SimpleSizer(_VarintSize) 132 | UInt64Sizer = UInt32Sizer 133 | 134 | SInt32Sizer = _ModifiedSizer(_SignedVarintSize, wire_format.ZigZagEncode) 135 | SInt64Sizer = SInt32Sizer 136 | 137 | Fixed32Sizer = _FixedSizer(4) 138 | SFixed32Sizer = Fixed32Sizer 139 | FloatSizer = Fixed32Sizer 140 | 141 | Fixed64Sizer = _FixedSizer(8) 142 | SFixed64Sizer = Fixed64Sizer 143 | DoubleSizer = Fixed64Sizer 144 | 145 | BoolSizer = _FixedSizer(1) 146 | 147 | 148 | function StringSizer(field_number, is_repeated, is_packed) 149 | local tag_size = _TagSize(field_number) 150 | local VarintSize = _VarintSize 151 | assert(not is_packed) 152 | if is_repeated then 153 | return function(value) 154 | local result = tag_size * #value 155 | for _, element in ipairs(value) do 156 | local l = #element 157 | result = result + VarintSize(l) + l 158 | end 159 | return result 160 | end 161 | else 162 | return function(value) 163 | local l = #value 164 | return tag_size + VarintSize(l) + l 165 | end 166 | end 167 | end 168 | 169 | function BytesSizer(field_number, is_repeated, is_packed) 170 | local tag_size = _TagSize(field_number) 171 | local VarintSize = _VarintSize 172 | assert(not is_packed) 173 | if is_repeated then 174 | return function (value) 175 | local result = tag_size * #value 176 | for _,element in ipairs(value) do 177 | local l = #element 178 | result = result + VarintSize(l) + l 179 | end 180 | return result 181 | end 182 | else 183 | return function (value) 184 | local l = #value 185 | return tag_size + VarintSize(l) + l 186 | end 187 | end 188 | end 189 | 190 | function MessageSizer(field_number, is_repeated, is_packed) 191 | local tag_size = _TagSize(field_number) 192 | local VarintSize = _VarintSize 193 | assert(not is_packed) 194 | if is_repeated then 195 | return function(value) 196 | local result = tag_size * #value 197 | for _,element in ipairs(value) do 198 | local l = element:ByteSize() 199 | result = result + VarintSize(l) + l 200 | end 201 | return result 202 | end 203 | else 204 | return function (value) 205 | local l = value:ByteSize() 206 | return tag_size + VarintSize(l) + l 207 | end 208 | end 209 | end 210 | 211 | 212 | -- ==================================================================== 213 | -- Encoders! 214 | 215 | local _EncodeVarint = pb.varint_encoder 216 | local _EncodeSignedVarint = pb.signed_varint_encoder 217 | 218 | 219 | function _VarintBytes(value) 220 | local out = {} 221 | local write = function(value) 222 | out[#out + 1 ] = value 223 | end 224 | _EncodeSignedVarint(write, value) 225 | return table.concat(out) 226 | end 227 | 228 | function TagBytes(field_number, wire_type) 229 | return _VarintBytes(wire_format.PackTag(field_number, wire_type)) 230 | end 231 | 232 | function _SimpleEncoder(wire_type, encode_value, compute_value_size) 233 | return function(field_number, is_repeated, is_packed) 234 | if is_packed then 235 | local tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 236 | local EncodeVarint = _EncodeVarint 237 | return function(write, value) 238 | write(tag_bytes) 239 | local size = 0 240 | for _, element in ipairs(value) do 241 | size = size + compute_value_size(element) 242 | end 243 | EncodeVarint(write, size) 244 | for element in value do 245 | encode_value(write, element) 246 | end 247 | end 248 | elseif is_repeated then 249 | local tag_bytes = TagBytes(field_number, wire_type) 250 | return function(write, value) 251 | for _, element in ipairs(value) do 252 | write(tag_bytes) 253 | encode_value(write, element) 254 | end 255 | end 256 | else 257 | local tag_bytes = TagBytes(field_number, wire_type) 258 | return function(write, value) 259 | write(tag_bytes) 260 | encode_value(write, value) 261 | end 262 | end 263 | end 264 | end 265 | 266 | function _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value) 267 | return function (field_number, is_repeated, is_packed) 268 | if is_packed then 269 | local tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 270 | local EncodeVarint = _EncodeVarint 271 | return function (write, value) 272 | write(tag_bytes) 273 | local size = 0 274 | for _, element in ipairs(value) do 275 | size = size + compute_value_size(modify_value(element)) 276 | end 277 | EncodeVarint(write, size) 278 | for _, element in ipairs(value) do 279 | encode_value(write, modify_value(element)) 280 | end 281 | end 282 | elseif is_repeated then 283 | local tag_bytes = TagBytes(field_number, wire_type) 284 | return function (write, value) 285 | for _, element in ipairs(value) do 286 | write(tag_bytes) 287 | encode_value(write, modify_value(element)) 288 | end 289 | end 290 | else 291 | local tag_bytes = TagBytes(field_number, wire_type) 292 | return function (write, value) 293 | write(tag_bytes) 294 | encode_value(write, modify_value(value)) 295 | end 296 | end 297 | end 298 | end 299 | 300 | function _StructPackEncoder(wire_type, value_size, format) 301 | return function(field_number, is_repeated, is_packed) 302 | local struct_pack = pb.struct_pack 303 | if is_packed then 304 | local tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 305 | local EncodeVarint = _EncodeVarint 306 | return function (write, value) 307 | write(tag_bytes) 308 | EncodeVarint(write, #value * value_size) 309 | for _, element in ipairs(value) do 310 | struct_pack(write, format, element) 311 | end 312 | end 313 | elseif is_repeated then 314 | local tag_bytes = TagBytes(field_number, wire_type) 315 | return function (write, value) 316 | for _, element in ipairs(value) do 317 | write(tag_bytes) 318 | struct_pack(write, format, element) 319 | end 320 | end 321 | else 322 | local tag_bytes = TagBytes(field_number, wire_type) 323 | return function (write, value) 324 | write(tag_bytes) 325 | struct_pack(write, format, value) 326 | end 327 | end 328 | 329 | end 330 | end 331 | 332 | Int32Encoder = _SimpleEncoder(wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) 333 | Int64Encoder = Int32Encoder 334 | EnumEncoder = Int32Encoder 335 | 336 | UInt32Encoder = _SimpleEncoder(wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) 337 | UInt64Encoder = UInt32Encoder 338 | 339 | SInt32Encoder = _ModifiedEncoder( 340 | wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, 341 | wire_format.ZigZagEncode32) 342 | 343 | SInt64Encoder = _ModifiedEncoder( 344 | wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, 345 | wire_format.ZigZagEncode64) 346 | 347 | Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('I')) 348 | Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('Q')) 349 | SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('i')) 350 | SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('q')) 351 | FloatEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, 4, string.byte('f')) 352 | DoubleEncoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, 8, string.byte('d')) 353 | 354 | 355 | function BoolEncoder(field_number, is_repeated, is_packed) 356 | local false_byte = '\0' 357 | local true_byte = '\1' 358 | if is_packed then 359 | local tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 360 | local EncodeVarint = _EncodeVarint 361 | return function (write, value) 362 | write(tag_bytes) 363 | EncodeVarint(write, #value) 364 | for _, element in ipairs(value) do 365 | if element then 366 | write(true_byte) 367 | else 368 | write(false_byte) 369 | end 370 | end 371 | end 372 | elseif is_repeated then 373 | local tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 374 | return function(write, value) 375 | for _, element in ipairs(value) do 376 | write(tag_bytes) 377 | if element then 378 | write(true_byte) 379 | else 380 | write(false_byte) 381 | end 382 | end 383 | end 384 | else 385 | local tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 386 | return function (write, value) 387 | write(tag_bytes) 388 | if value then 389 | return write(true_byte) 390 | end 391 | return write(false_byte) 392 | end 393 | end 394 | end 395 | 396 | function StringEncoder(field_number, is_repeated, is_packed) 397 | local tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 398 | local EncodeVarint = _EncodeVarint 399 | assert(not is_packed) 400 | if is_repeated then 401 | return function (write, value) 402 | for _, element in ipairs(value) do 403 | -- encoded = element.encode('utf-8') 404 | write(tag) 405 | EncodeVarint(write, #element) 406 | write(element) 407 | end 408 | end 409 | else 410 | return function (write, value) 411 | -- local encoded = value.encode('utf-8') 412 | write(tag) 413 | EncodeVarint(write, #value) 414 | return write(value) 415 | end 416 | end 417 | end 418 | 419 | function BytesEncoder(field_number, is_repeated, is_packed) 420 | local tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 421 | local EncodeVarint = _EncodeVarint 422 | assert(not is_packed) 423 | if is_repeated then 424 | return function (write, value) 425 | for _, element in ipairs(value) do 426 | write(tag) 427 | EncodeVarint(write, #element) 428 | write(element) 429 | end 430 | end 431 | else 432 | return function(write, value) 433 | write(tag) 434 | EncodeVarint(write, #value) 435 | return write(value) 436 | end 437 | end 438 | end 439 | 440 | 441 | function MessageEncoder(field_number, is_repeated, is_packed) 442 | local tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 443 | local EncodeVarint = _EncodeVarint 444 | assert(not is_packed) 445 | if is_repeated then 446 | return function(write, value) 447 | for _, element in ipairs(value) do 448 | write(tag) 449 | EncodeVarint(write, element:ByteSize()) 450 | element:_InternalSerialize(write) 451 | end 452 | end 453 | else 454 | return function (write, value) 455 | write(tag) 456 | EncodeVarint(write, value:ByteSize()) 457 | return value:_InternalSerialize(write) 458 | end 459 | end 460 | end 461 | 462 | -------------------------------------------------------------------------------- /protobuf/protobuf.lua: -------------------------------------------------------------------------------- 1 | -- 2 | -------------------------------------------------------------------------------- 3 | -- FILE: protobuf.lua 4 | -- DESCRIPTION: protoc-gen-lua 5 | -- Google's Protocol Buffers project, ported to lua. 6 | -- https://code.google.com/p/protoc-gen-lua/ 7 | -- 8 | -- Copyright (c) 2010 , 林卓毅 (Zhuoyi Lin) netsnail@gmail.com 9 | -- All rights reserved. 10 | -- 11 | -- Use, modification and distribution are subject to the "New BSD License" 12 | -- as listed at . 13 | -- 14 | -- COMPANY: NetEase 15 | -- CREATED: 2010年07月29日 14时30分02秒 CST 16 | -------------------------------------------------------------------------------- 17 | -- 18 | 19 | local setmetatable = setmetatable 20 | local rawset = rawset 21 | local rawget = rawget 22 | local error = error 23 | local ipairs = ipairs 24 | local pairs = pairs 25 | local print = print 26 | local table = table 27 | local string = string 28 | local tostring = tostring 29 | local type = type 30 | 31 | local pb = require "pb" 32 | local wire_format = require "wire_format" 33 | local type_checkers = require "type_checkers" 34 | local encoder = require "encoder" 35 | local decoder = require "decoder" 36 | local listener_mod = require "listener" 37 | local containers = require "containers" 38 | local descriptor = require "descriptor" 39 | local FieldDescriptor = descriptor.FieldDescriptor 40 | local text_format = require "text_format" 41 | 42 | module("protobuf") 43 | 44 | local function make_descriptor(name, descriptor, usable_key) 45 | local meta = { 46 | __newindex = function(self, key, value) 47 | if usable_key[key] then 48 | rawset(self, key, value) 49 | else 50 | error("error key: "..key) 51 | end 52 | end 53 | }; 54 | meta.__index = meta 55 | meta.__call = function() 56 | return setmetatable({}, meta) 57 | end 58 | 59 | _M[name] = setmetatable(descriptor, meta); 60 | end 61 | 62 | 63 | make_descriptor("Descriptor", {}, { 64 | name = true, 65 | full_name = true, 66 | filename = true, 67 | containing_type = true, 68 | fields = true, 69 | nested_types = true, 70 | enum_types = true, 71 | extensions = true, 72 | options = true, 73 | is_extendable = true, 74 | extension_ranges = true, 75 | }) 76 | 77 | make_descriptor("FieldDescriptor", FieldDescriptor, { 78 | name = true, 79 | full_name = true, 80 | index = true, 81 | number = true, 82 | type = true, 83 | cpp_type = true, 84 | label = true, 85 | has_default_value = true, 86 | default_value = true, 87 | containing_type = true, 88 | message_type = true, 89 | enum_type = true, 90 | is_extension = true, 91 | extension_scope = true, 92 | }) 93 | 94 | make_descriptor("EnumDescriptor", {}, { 95 | name = true, 96 | full_name = true, 97 | values = true, 98 | containing_type = true, 99 | options = true 100 | }) 101 | 102 | make_descriptor("EnumValueDescriptor", {}, { 103 | name = true, 104 | index = true, 105 | number = true, 106 | type = true, 107 | options = true 108 | }) 109 | 110 | -- Maps from field type to expected wiretype. 111 | local FIELD_TYPE_TO_WIRE_TYPE = { 112 | [FieldDescriptor.TYPE_DOUBLE] = wire_format.WIRETYPE_FIXED64, 113 | [FieldDescriptor.TYPE_FLOAT] = wire_format.WIRETYPE_FIXED32, 114 | [FieldDescriptor.TYPE_INT64] = wire_format.WIRETYPE_VARINT, 115 | [FieldDescriptor.TYPE_UINT64] = wire_format.WIRETYPE_VARINT, 116 | [FieldDescriptor.TYPE_INT32] = wire_format.WIRETYPE_VARINT, 117 | [FieldDescriptor.TYPE_FIXED64] = wire_format.WIRETYPE_FIXED64, 118 | [FieldDescriptor.TYPE_FIXED32] = wire_format.WIRETYPE_FIXED32, 119 | [FieldDescriptor.TYPE_BOOL] = wire_format.WIRETYPE_VARINT, 120 | [FieldDescriptor.TYPE_STRING] = wire_format.WIRETYPE_LENGTH_DELIMITED, 121 | [FieldDescriptor.TYPE_GROUP] = wire_format.WIRETYPE_START_GROUP, 122 | [FieldDescriptor.TYPE_MESSAGE] = wire_format.WIRETYPE_LENGTH_DELIMITED, 123 | [FieldDescriptor.TYPE_BYTES] = wire_format.WIRETYPE_LENGTH_DELIMITED, 124 | [FieldDescriptor.TYPE_UINT32] = wire_format.WIRETYPE_VARINT, 125 | [FieldDescriptor.TYPE_ENUM] = wire_format.WIRETYPE_VARINT, 126 | [FieldDescriptor.TYPE_SFIXED32] = wire_format.WIRETYPE_FIXED32, 127 | [FieldDescriptor.TYPE_SFIXED64] = wire_format.WIRETYPE_FIXED64, 128 | [FieldDescriptor.TYPE_SINT32] = wire_format.WIRETYPE_VARINT, 129 | [FieldDescriptor.TYPE_SINT64] = wire_format.WIRETYPE_VARINT 130 | } 131 | 132 | local NON_PACKABLE_TYPES = { 133 | [FieldDescriptor.TYPE_STRING] = true, 134 | [FieldDescriptor.TYPE_GROUP] = true, 135 | [FieldDescriptor.TYPE_MESSAGE] = true, 136 | [FieldDescriptor.TYPE_BYTES] = true 137 | } 138 | 139 | local _VALUE_CHECKERS = { 140 | [FieldDescriptor.CPPTYPE_INT32] = type_checkers.Int32ValueChecker(), 141 | [FieldDescriptor.CPPTYPE_INT64] = type_checkers.Int32ValueChecker(), 142 | [FieldDescriptor.CPPTYPE_UINT32] = type_checkers.Uint32ValueChecker(), 143 | [FieldDescriptor.CPPTYPE_UINT64] = type_checkers.Uint32ValueChecker(), 144 | [FieldDescriptor.CPPTYPE_DOUBLE] = type_checkers.TypeChecker({number = true}), 145 | [FieldDescriptor.CPPTYPE_FLOAT] = type_checkers.TypeChecker({number = true}), 146 | [FieldDescriptor.CPPTYPE_BOOL] = type_checkers.TypeChecker({boolean = true, bool = true, int=true}), 147 | [FieldDescriptor.CPPTYPE_ENUM] = type_checkers.Int32ValueChecker(), 148 | [FieldDescriptor.CPPTYPE_STRING] = type_checkers.TypeChecker({string = true}) 149 | } 150 | 151 | 152 | local TYPE_TO_BYTE_SIZE_FN = { 153 | [FieldDescriptor.TYPE_DOUBLE] = wire_format.DoubleByteSize, 154 | [FieldDescriptor.TYPE_FLOAT] = wire_format.FloatByteSize, 155 | [FieldDescriptor.TYPE_INT64] = wire_format.Int64ByteSize, 156 | [FieldDescriptor.TYPE_UINT64] = wire_format.UInt64ByteSize, 157 | [FieldDescriptor.TYPE_INT32] = wire_format.Int32ByteSize, 158 | [FieldDescriptor.TYPE_FIXED64] = wire_format.Fixed64ByteSize, 159 | [FieldDescriptor.TYPE_FIXED32] = wire_format.Fixed32ByteSize, 160 | [FieldDescriptor.TYPE_BOOL] = wire_format.BoolByteSize, 161 | [FieldDescriptor.TYPE_STRING] = wire_format.StringByteSize, 162 | [FieldDescriptor.TYPE_GROUP] = wire_format.GroupByteSize, 163 | [FieldDescriptor.TYPE_MESSAGE] = wire_format.MessageByteSize, 164 | [FieldDescriptor.TYPE_BYTES] = wire_format.BytesByteSize, 165 | [FieldDescriptor.TYPE_UINT32] = wire_format.UInt32ByteSize, 166 | [FieldDescriptor.TYPE_ENUM] = wire_format.EnumByteSize, 167 | [FieldDescriptor.TYPE_SFIXED32] = wire_format.SFixed32ByteSize, 168 | [FieldDescriptor.TYPE_SFIXED64] = wire_format.SFixed64ByteSize, 169 | [FieldDescriptor.TYPE_SINT32] = wire_format.SInt32ByteSize, 170 | [FieldDescriptor.TYPE_SINT64] = wire_format.SInt64ByteSize 171 | } 172 | 173 | local TYPE_TO_ENCODER = { 174 | [FieldDescriptor.TYPE_DOUBLE] = encoder.DoubleEncoder, 175 | [FieldDescriptor.TYPE_FLOAT] = encoder.FloatEncoder, 176 | [FieldDescriptor.TYPE_INT64] = encoder.Int64Encoder, 177 | [FieldDescriptor.TYPE_UINT64] = encoder.UInt64Encoder, 178 | [FieldDescriptor.TYPE_INT32] = encoder.Int32Encoder, 179 | [FieldDescriptor.TYPE_FIXED64] = encoder.Fixed64Encoder, 180 | [FieldDescriptor.TYPE_FIXED32] = encoder.Fixed32Encoder, 181 | [FieldDescriptor.TYPE_BOOL] = encoder.BoolEncoder, 182 | [FieldDescriptor.TYPE_STRING] = encoder.StringEncoder, 183 | [FieldDescriptor.TYPE_GROUP] = encoder.GroupEncoder, 184 | [FieldDescriptor.TYPE_MESSAGE] = encoder.MessageEncoder, 185 | [FieldDescriptor.TYPE_BYTES] = encoder.BytesEncoder, 186 | [FieldDescriptor.TYPE_UINT32] = encoder.UInt32Encoder, 187 | [FieldDescriptor.TYPE_ENUM] = encoder.EnumEncoder, 188 | [FieldDescriptor.TYPE_SFIXED32] = encoder.SFixed32Encoder, 189 | [FieldDescriptor.TYPE_SFIXED64] = encoder.SFixed64Encoder, 190 | [FieldDescriptor.TYPE_SINT32] = encoder.SInt32Encoder, 191 | [FieldDescriptor.TYPE_SINT64] = encoder.SInt64Encoder 192 | } 193 | 194 | local TYPE_TO_SIZER = { 195 | [FieldDescriptor.TYPE_DOUBLE] = encoder.DoubleSizer, 196 | [FieldDescriptor.TYPE_FLOAT] = encoder.FloatSizer, 197 | [FieldDescriptor.TYPE_INT64] = encoder.Int64Sizer, 198 | [FieldDescriptor.TYPE_UINT64] = encoder.UInt64Sizer, 199 | [FieldDescriptor.TYPE_INT32] = encoder.Int32Sizer, 200 | [FieldDescriptor.TYPE_FIXED64] = encoder.Fixed64Sizer, 201 | [FieldDescriptor.TYPE_FIXED32] = encoder.Fixed32Sizer, 202 | [FieldDescriptor.TYPE_BOOL] = encoder.BoolSizer, 203 | [FieldDescriptor.TYPE_STRING] = encoder.StringSizer, 204 | [FieldDescriptor.TYPE_GROUP] = encoder.GroupSizer, 205 | [FieldDescriptor.TYPE_MESSAGE] = encoder.MessageSizer, 206 | [FieldDescriptor.TYPE_BYTES] = encoder.BytesSizer, 207 | [FieldDescriptor.TYPE_UINT32] = encoder.UInt32Sizer, 208 | [FieldDescriptor.TYPE_ENUM] = encoder.EnumSizer, 209 | [FieldDescriptor.TYPE_SFIXED32] = encoder.SFixed32Sizer, 210 | [FieldDescriptor.TYPE_SFIXED64] = encoder.SFixed64Sizer, 211 | [FieldDescriptor.TYPE_SINT32] = encoder.SInt32Sizer, 212 | [FieldDescriptor.TYPE_SINT64] = encoder.SInt64Sizer 213 | } 214 | 215 | local TYPE_TO_DECODER = { 216 | [FieldDescriptor.TYPE_DOUBLE] = decoder.DoubleDecoder, 217 | [FieldDescriptor.TYPE_FLOAT] = decoder.FloatDecoder, 218 | [FieldDescriptor.TYPE_INT64] = decoder.Int64Decoder, 219 | [FieldDescriptor.TYPE_UINT64] = decoder.UInt64Decoder, 220 | [FieldDescriptor.TYPE_INT32] = decoder.Int32Decoder, 221 | [FieldDescriptor.TYPE_FIXED64] = decoder.Fixed64Decoder, 222 | [FieldDescriptor.TYPE_FIXED32] = decoder.Fixed32Decoder, 223 | [FieldDescriptor.TYPE_BOOL] = decoder.BoolDecoder, 224 | [FieldDescriptor.TYPE_STRING] = decoder.StringDecoder, 225 | [FieldDescriptor.TYPE_GROUP] = decoder.GroupDecoder, 226 | [FieldDescriptor.TYPE_MESSAGE] = decoder.MessageDecoder, 227 | [FieldDescriptor.TYPE_BYTES] = decoder.BytesDecoder, 228 | [FieldDescriptor.TYPE_UINT32] = decoder.UInt32Decoder, 229 | [FieldDescriptor.TYPE_ENUM] = decoder.EnumDecoder, 230 | [FieldDescriptor.TYPE_SFIXED32] = decoder.SFixed32Decoder, 231 | [FieldDescriptor.TYPE_SFIXED64] = decoder.SFixed64Decoder, 232 | [FieldDescriptor.TYPE_SINT32] = decoder.SInt32Decoder, 233 | [FieldDescriptor.TYPE_SINT64] = decoder.SInt64Decoder 234 | } 235 | 236 | local FIELD_TYPE_TO_WIRE_TYPE = { 237 | [FieldDescriptor.TYPE_DOUBLE] = wire_format.WIRETYPE_FIXED64, 238 | [FieldDescriptor.TYPE_FLOAT] = wire_format.WIRETYPE_FIXED32, 239 | [FieldDescriptor.TYPE_INT64] = wire_format.WIRETYPE_VARINT, 240 | [FieldDescriptor.TYPE_UINT64] = wire_format.WIRETYPE_VARINT, 241 | [FieldDescriptor.TYPE_INT32] = wire_format.WIRETYPE_VARINT, 242 | [FieldDescriptor.TYPE_FIXED64] = wire_format.WIRETYPE_FIXED64, 243 | [FieldDescriptor.TYPE_FIXED32] = wire_format.WIRETYPE_FIXED32, 244 | [FieldDescriptor.TYPE_BOOL] = wire_format.WIRETYPE_VARINT, 245 | [FieldDescriptor.TYPE_STRING] = wire_format.WIRETYPE_LENGTH_DELIMITED, 246 | [FieldDescriptor.TYPE_GROUP] = wire_format.WIRETYPE_START_GROUP, 247 | [FieldDescriptor.TYPE_MESSAGE] = wire_format.WIRETYPE_LENGTH_DELIMITED, 248 | [FieldDescriptor.TYPE_BYTES] = wire_format.WIRETYPE_LENGTH_DELIMITED, 249 | [FieldDescriptor.TYPE_UINT32] = wire_format.WIRETYPE_VARINT, 250 | [FieldDescriptor.TYPE_ENUM] = wire_format.WIRETYPE_VARINT, 251 | [FieldDescriptor.TYPE_SFIXED32] = wire_format.WIRETYPE_FIXED32, 252 | [FieldDescriptor.TYPE_SFIXED64] = wire_format.WIRETYPE_FIXED64, 253 | [FieldDescriptor.TYPE_SINT32] = wire_format.WIRETYPE_VARINT, 254 | [FieldDescriptor.TYPE_SINT64] = wire_format.WIRETYPE_VARINT 255 | } 256 | 257 | local function IsTypePackable(field_type) 258 | return NON_PACKABLE_TYPES[field_type] == nil 259 | end 260 | 261 | local function GetTypeChecker(cpp_type, field_type) 262 | if (cpp_type == FieldDescriptor.CPPTYPE_STRING and field_type == FieldDescriptor.TYPE_STRING) then 263 | return type_checkers.UnicodeValueChecker() 264 | end 265 | return _VALUE_CHECKERS[cpp_type] 266 | end 267 | 268 | local function _DefaultValueConstructorForField(field) 269 | if field.label == FieldDescriptor.LABEL_REPEATED then 270 | if type(field.default_value) ~= "table" or #(field.default_value) ~= 0 then 271 | error('Repeated field default value not empty list:' .. tostring(field.default_value)) 272 | end 273 | if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 274 | local message_type = field.message_type 275 | return function (message) 276 | return containers.RepeatedCompositeFieldContainer(message._listener_for_children, message_type) 277 | end 278 | else 279 | local type_checker = GetTypeChecker(field.cpp_type, field.type) 280 | return function (message) 281 | return containers.RepeatedScalarFieldContainer(message._listener_for_children, type_checker) 282 | end 283 | end 284 | end 285 | if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 286 | local message_type = field.message_type 287 | return function (message) 288 | result = message_type._concrete_class() 289 | result._SetListener(message._listener_for_children) 290 | return result 291 | end 292 | end 293 | return function (message) 294 | return field.default_value 295 | end 296 | end 297 | 298 | local function _AttachFieldHelpers(message_meta, field_descriptor) 299 | local is_repeated = (field_descriptor.label == FieldDescriptor.LABEL_REPEATED) 300 | local is_packed = (field_descriptor.has_options and field_descriptor.GetOptions().packed) 301 | 302 | rawset(field_descriptor, "_encoder", TYPE_TO_ENCODER[field_descriptor.type](field_descriptor.number, is_repeated, is_packed)) 303 | rawset(field_descriptor, "_sizer", TYPE_TO_SIZER[field_descriptor.type](field_descriptor.number, is_repeated, is_packed)) 304 | rawset(field_descriptor, "_default_constructor", _DefaultValueConstructorForField(field_descriptor)) 305 | 306 | local AddDecoder = function(wiretype, is_packed) 307 | local tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype) 308 | message_meta._decoders_by_tag[tag_bytes] = TYPE_TO_DECODER[field_descriptor.type](field_descriptor.number, is_repeated, is_packed, field_descriptor, field_descriptor._default_constructor) 309 | end 310 | 311 | AddDecoder(FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], False) 312 | if is_repeated and IsTypePackable(field_descriptor.type) then 313 | AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True) 314 | end 315 | end 316 | 317 | local function _AddEnumValues(descriptor, message_meta) 318 | for _, enum_type in ipairs(descriptor.enum_types) do 319 | for _, enum_value in ipairs(enum_type.values) do 320 | message_meta._member[enum_value.name] = enum_value.number 321 | end 322 | end 323 | end 324 | 325 | local function _InitMethod(message_meta) 326 | return function() 327 | local self = {} 328 | self._cached_byte_size = 0 329 | self._cached_byte_size_dirty = false 330 | self._fields = {} 331 | self._is_present_in_parent = false 332 | self._listener = listener_mod.NullMessageListener() 333 | self._listener_for_children = listener_mod.Listener(self) 334 | return setmetatable(self, message_meta) 335 | end 336 | end 337 | 338 | local function _AddPropertiesForRepeatedField(field, message_meta) 339 | local property_name = field.name 340 | 341 | message_meta._getter[property_name] = function(self) 342 | local field_value = self._fields[field] 343 | if field_value == nil then 344 | field_value = field._default_constructor(self) 345 | 346 | self._fields[field] = field_value 347 | end 348 | return field_value 349 | end 350 | 351 | message_meta._setter[property_name] = function(self) 352 | error('Assignment not allowed to repeated field "' .. property_name .. '" in protocol message object.') 353 | end 354 | end 355 | 356 | local function _AddPropertiesForNonRepeatedCompositeField(field, message_meta) 357 | local property_name = field.name 358 | local message_type = field.message_type 359 | 360 | message_meta._getter[property_name] = function(self) 361 | local field_value = self._fields[field] 362 | if field_value == nil then 363 | field_value = message_type._concrete_class() 364 | field_value:_SetListener(self._listener_for_children) 365 | 366 | self._fields[field] = field_value 367 | end 368 | return field_value 369 | end 370 | message_meta._setter[property_name] = function(self, new_value) 371 | error('Assignment not allowed to composite field' .. property_name .. 'in protocol message object.' ) 372 | end 373 | end 374 | 375 | local function _AddPropertiesForNonRepeatedScalarField(field, message) 376 | local property_name = field.name 377 | local type_checker = GetTypeChecker(field.cpp_type, field.type) 378 | local default_value = field.default_value 379 | 380 | message._getter[property_name] = function(self) 381 | local value = self._fields[field] 382 | if value ~= nil then 383 | return self._fields[field] 384 | else 385 | return default_value 386 | end 387 | end 388 | 389 | message._setter[property_name] = function(self, new_value) 390 | type_checker(new_value) 391 | self._fields[field] = new_value 392 | if not self._cached_byte_size_dirty then 393 | message._member._Modified(self) 394 | end 395 | end 396 | end 397 | 398 | local function _AddPropertiesForField(field, message_meta) 399 | constant_name = field.name:upper() .. "_FIELD_NUMBER" 400 | message_meta._member[constant_name] = field.number 401 | 402 | if field.label == FieldDescriptor.LABEL_REPEATED then 403 | _AddPropertiesForRepeatedField(field, message_meta) 404 | elseif field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 405 | _AddPropertiesForNonRepeatedCompositeField(field, message_meta) 406 | else 407 | _AddPropertiesForNonRepeatedScalarField(field, message_meta) 408 | end 409 | end 410 | 411 | local _ED_meta = { 412 | __index = function(self, extension_handle) 413 | local _extended_message = rawget(self, "_extended_message") 414 | local value = _extended_message._fields[extension_handle] 415 | if value ~= nil then 416 | return value 417 | end 418 | if extension_handle.label == FieldDescriptor.LABEL_REPEATED then 419 | value = extension_handle._default_constructor(self._extended_message) 420 | elseif extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 421 | value = extension_handle.message_type._concrete_class() 422 | value:_SetListener(_extended_message._listener_for_children) 423 | else 424 | return extension_handle.default_value 425 | end 426 | _extended_message._fields[extension_handle] = value 427 | return value 428 | end, 429 | __newindex = function(self, extension_handle, value) 430 | local _extended_message = rawget(self, "_extended_message") 431 | if (extension_handle.label == FieldDescriptor.LABEL_REPEATED or 432 | extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE) then 433 | error('Cannot assign to extension "'.. extension_handle.full_name .. '" because it is a repeated or composite type.') 434 | end 435 | 436 | local type_checker = GetTypeChecker(extension_handle.cpp_type, extension_handle.type) 437 | type_checker.CheckValue(value) 438 | _extended_message._fields[extension_handle] = value 439 | _extended_message._Modified() 440 | end 441 | } 442 | 443 | local function _ExtensionDict(message) 444 | local o = {} 445 | o._extended_message = message 446 | return setmetatable(o, _ED_meta) 447 | end 448 | 449 | local function _AddPropertiesForFields(descriptor, message_meta) 450 | for _, field in ipairs(descriptor.fields) do 451 | _AddPropertiesForField(field, message_meta) 452 | end 453 | if descriptor.is_extendable then 454 | message_meta._getter.Extensions = function(self) return _ExtensionDict(self) end 455 | end 456 | end 457 | 458 | local function _AddPropertiesForExtensions(descriptor, message_meta) 459 | local extension_dict = descriptor._extensions_by_name 460 | for extension_name, extension_field in pairs(extension_dict) do 461 | local constant_name = string.upper(extension_name) .. "_FIELD_NUMBER" 462 | message_meta._member[constant_name] = extension_field.number 463 | end 464 | end 465 | 466 | local function _AddStaticMethods(message_meta) 467 | message_meta._member.RegisterExtension = function(extension_handle) 468 | extension_handle.containing_type = message_meta._descriptor 469 | _AttachFieldHelpers(message_meta, extension_handle) 470 | 471 | if message_meta._extensions_by_number[extension_handle.number] == nil then 472 | message_meta._extensions_by_number[extension_handle.number] = extension_handle 473 | else 474 | error( 475 | string.format('Extensions "%s" and "%s" both try to extend message type "%s" with field number %d.', 476 | extension_handle.full_name, actual_handle.full_name, 477 | message_meta._descriptor.full_name, extension_handle.number)) 478 | end 479 | message_meta._extensions_by_name[extension_handle.full_name] = extension_handle 480 | end 481 | 482 | message_meta._member.FromString = function(s) 483 | local message = message_meta._member.__call() 484 | message.MergeFromString(s) 485 | return message 486 | end 487 | end 488 | 489 | local function _IsPresent(descriptor, value) 490 | if descriptor.label == FieldDescriptor.LABEL_REPEATED then 491 | return value 492 | elseif descriptor.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 493 | return value._is_present_in_parent 494 | else 495 | return true 496 | end 497 | end 498 | 499 | local function _AddListFieldsMethod(message_descriptor, message_meta) 500 | message_meta._member.ListFields = function (self) 501 | local list_field = function(fields) 502 | local f, s, v = pairs(self._fields) 503 | local iter = function(a, i) 504 | while true do 505 | local descriptor, value = f(a, i) 506 | if descriptor == nil then 507 | return 508 | elseif _IsPresent(descriptor, value) then 509 | return descriptor, value 510 | end 511 | end 512 | end 513 | return iter, s, v 514 | end 515 | return list_field(self._fields) 516 | end 517 | end 518 | 519 | local function _AddHasFieldMethod(message_descriptor, message_meta) 520 | local singular_fields = {} 521 | for _, field in ipairs(message_descriptor.fields) do 522 | if field.label ~= FieldDescriptor.LABEL_REPEATED then 523 | singular_fields[field.name] = field 524 | end 525 | end 526 | message_meta._member.HasField = function (self, field_name) 527 | field = singular_fields[field_name] 528 | if field == nil then 529 | error('Protocol message has no singular "'.. field_name.. '" field.') 530 | end 531 | if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 532 | value = self._fields[field] 533 | return value ~= nil and value._is_present_in_parent 534 | else 535 | return self._fields[field] 536 | end 537 | end 538 | end 539 | 540 | local function _AddClearFieldMethod(message_descriptor, message_meta) 541 | message_meta._member.ClearField = function(self, field_name) 542 | if message_descriptor.fields_by_name[field_name] == nil then 543 | error('Protocol message has no "' .. field_name .. '" field.') 544 | end 545 | 546 | if self._fields[field] then 547 | self._fields[field] = nil 548 | end 549 | message_meta._member._Modified(self) 550 | end 551 | end 552 | 553 | local function _AddClearExtensionMethod(message_meta) 554 | message_meta._member.ClearExtension = function(self, extension_handle) 555 | if self._fields[extension_handle] == nil then 556 | self._fields[extension_handle] = nil 557 | end 558 | message_meta._member._Modified(self) 559 | end 560 | end 561 | 562 | local function _AddClearMethod(message_descriptor, message_meta) 563 | message_meta._member.Clear = function(self) 564 | self._fields = {} 565 | message_meta._member._Modified(self) 566 | end 567 | end 568 | 569 | local function _AddStrMethod(message_meta) 570 | local format = text_format.msg_format 571 | message_meta.__tostring = function(self) 572 | return format(self) 573 | end 574 | end 575 | 576 | local function _AddHasExtensionMethod(message_meta) 577 | message_meta._member.HasExtension = function(self, extension_handle) 578 | if extension_handle.label == FieldDescriptor.LABEL_REPEATED then 579 | error(extension_handle.full_name .. ' is repeated.') 580 | end 581 | if extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 582 | value = self._fields[extension_handle] 583 | return value ~= nil and value._is_present_in_parent 584 | else 585 | return self._fields[extension_handle] 586 | end 587 | end 588 | end 589 | 590 | local function _AddSetListenerMethod(message_meta) 591 | message_meta._member._SetListener = function(self, listener) 592 | if listener ~= nil then 593 | self._listener = listener_mod.NullMessageListener() 594 | else 595 | self._listener = listener 596 | end 597 | end 598 | end 599 | 600 | local function _AddByteSizeMethod(message_descriptor, message_meta) 601 | message_meta._member.ByteSize = function(self) 602 | if not self._cached_byte_size_dirty then 603 | return self._cached_byte_size 604 | end 605 | local size = 0 606 | for field_descriptor, field_value in message_meta._member.ListFields(self) do 607 | size = field_descriptor._sizer(field_value) + size 608 | end 609 | self._cached_byte_size = size 610 | self._cached_byte_size_dirty = false 611 | self._listener_for_children.dirty = false 612 | return size 613 | end 614 | end 615 | 616 | local function _AddSerializeToStringMethod(message_descriptor, message_meta) 617 | message_meta._member.SerializeToString = function(self) 618 | if not message_meta._member.IsInitialized(self) then 619 | error('Message is missing required fields: ' .. 620 | table.concat(message_meta._member.FindInitializationErrors(self), ',')) 621 | end 622 | return message_meta._member.SerializePartialToString(self) 623 | end 624 | message_meta._member.SerializeToIOString = function(self, iostring) 625 | if not message_meta._member.IsInitialized(self) then 626 | error('Message is missing required fields: ' .. 627 | table.concat(message_meta._member.FindInitializationErrors(self), ',')) 628 | end 629 | return message_meta._member.SerializePartialToIOString(self, iostring) 630 | end 631 | end 632 | 633 | local function _AddSerializePartialToStringMethod(message_descriptor, message_meta) 634 | local concat = table.concat 635 | local _internal_serialize = function(self, write_bytes) 636 | for field_descriptor, field_value in message_meta._member.ListFields(self) do 637 | field_descriptor._encoder(write_bytes, field_value) 638 | end 639 | end 640 | 641 | local _serialize_partial_to_iostring = function(self, iostring) 642 | local w = iostring.write 643 | local write = function(value) 644 | w(iostring, value) 645 | end 646 | _internal_serialize(self, write) 647 | return 648 | end 649 | 650 | local _serialize_partial_to_string = function(self) 651 | local out = {} 652 | local write = function(value) 653 | out[#out + 1] = value 654 | end 655 | _internal_serialize(self, write) 656 | return concat(out) 657 | end 658 | 659 | message_meta._member._InternalSerialize = _internal_serialize 660 | message_meta._member.SerializePartialToIOString = _serialize_partial_to_iostring 661 | message_meta._member.SerializePartialToString = _serialize_partial_to_string 662 | end 663 | 664 | local function _AddMergeFromStringMethod(message_descriptor, message_meta) 665 | local ReadTag = decoder.ReadTag 666 | local SkipField = decoder.SkipField 667 | local decoders_by_tag = message_meta._decoders_by_tag 668 | 669 | local _internal_parse = function(self, buffer, pos, pend) 670 | message_meta._member._Modified(self) 671 | local field_dict = self._fields 672 | local tag_bytes, new_pos 673 | local field_decoder 674 | while pos ~= pend do 675 | tag_bytes, new_pos = ReadTag(buffer, pos) 676 | field_decoder = decoders_by_tag[tag_bytes] 677 | if field_decoder == nil then 678 | new_pos = SkipField(buffer, new_pos, pend, tag_bytes) 679 | if new_pos == -1 then 680 | return pos 681 | end 682 | pos = new_pos 683 | else 684 | pos = field_decoder(buffer, new_pos, pend, self, field_dict) 685 | end 686 | end 687 | return pos 688 | end 689 | message_meta._member._InternalParse = _internal_parse 690 | 691 | local merge_from_string = function(self, serialized) 692 | local length = #serialized 693 | if _internal_parse(self, serialized, 0, length) ~= length then 694 | error('Unexpected end-group tag.') 695 | end 696 | return length 697 | end 698 | message_meta._member.MergeFromString = merge_from_string 699 | 700 | message_meta._member.ParseFromString = function(self, serialized) 701 | message_meta._member.Clear(self) 702 | merge_from_string(self, serialized) 703 | end 704 | end 705 | 706 | local function _AddIsInitializedMethod(message_descriptor, message_meta) 707 | local required_fields = {} 708 | for _, field in ipairs(message_descriptor.fields) do 709 | if field.label == FieldDescriptor.LABEL_REQUIRED then 710 | required_fields[#required_fields + 1] = field 711 | end 712 | end 713 | 714 | message_meta._member.IsInitialized = function(self, errors) 715 | for _, field in ipairs(required_fields) do 716 | if self._fields[field] == nil or 717 | (field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE and not self._fields[field]._is_present_in_parent) then 718 | if errors ~= nil then 719 | errors[#errors + 1] = message_meta._member.FindInitializationErrors(self) 720 | end 721 | return false 722 | end 723 | end 724 | 725 | for field, value in pairs(self._fields) do 726 | if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 727 | if field.label == FieldDescriptor.LABEL_REPEATED then 728 | for _, element in ipairs(value) do 729 | if not element:IsInitialized() then 730 | if errors ~= nil then 731 | errors[#errors + 1] = message_meta._member.FindInitializationErrors(self) 732 | end 733 | return false 734 | end 735 | end 736 | elseif value._is_present_in_parent and not value:IsInitialized() then 737 | if errors ~= nil then 738 | errors[#errors + 1] = message_meta._member.FindInitializationErrors(self) 739 | end 740 | return false 741 | end 742 | end 743 | end 744 | return true 745 | end 746 | 747 | message_meta._member.FindInitializationErrors = function(self) 748 | local errors = {} 749 | 750 | for _,field in ipairs(required_fields) do 751 | if not message_meta._member.HasField(self, field.name) then 752 | errors.append(field.name) 753 | end 754 | end 755 | 756 | for field, value in message_meta._member.ListFields(self) do 757 | if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then 758 | if field.is_extension then 759 | name = io:format("(%s)", field.full_name) 760 | else 761 | name = field.name 762 | end 763 | if field.label == FieldDescriptor.LABEL_REPEATED then 764 | for i, element in ipairs(value) do 765 | prefix = io:format("%s[%d].", name, i) 766 | sub_errors = element:FindInitializationErrors() 767 | for _, e in ipairs(sub_errors) do 768 | errors[#errors + 1] = prefix .. e 769 | end 770 | end 771 | else 772 | prefix = name .. "." 773 | sub_errors = value:FindInitializationErrors() 774 | for _, e in ipairs(sub_errors) do 775 | errors[#errors + 1] = prefix .. e 776 | end 777 | end 778 | end 779 | end 780 | return errors 781 | end 782 | end 783 | 784 | local function _AddMergeFromMethod(message_meta) 785 | local LABEL_REPEATED = FieldDescriptor.LABEL_REPEATED 786 | local CPPTYPE_MESSAGE = FieldDescriptor.CPPTYPE_MESSAGE 787 | 788 | message_meta._member.MergeFrom = function (self, msg) 789 | assert(msg ~= self) 790 | message_meta._member._Modified(self) 791 | 792 | local fields = self._fields 793 | 794 | for field, value in pairs(msg._fields) do 795 | if field.label == LABEL_REPEATED or field.cpp_type == CPPTYPE_MESSAGE then 796 | field_value = fields[field] 797 | if field_value == nil then 798 | field_value = field._default_constructor(self) 799 | fields[field] = field_value 800 | end 801 | field_value:MergeFrom(value) 802 | else 803 | self._fields[field] = value 804 | end 805 | end 806 | end 807 | end 808 | 809 | local function _AddMessageMethods(message_descriptor, message_meta) 810 | _AddListFieldsMethod(message_descriptor, message_meta) 811 | _AddHasFieldMethod(message_descriptor, message_meta) 812 | _AddClearFieldMethod(message_descriptor, message_meta) 813 | if message_descriptor.is_extendable then 814 | _AddClearExtensionMethod(message_meta) 815 | _AddHasExtensionMethod(message_meta) 816 | end 817 | _AddClearMethod(message_descriptor, message_meta) 818 | -- _AddEqualsMethod(message_descriptor, message_meta) 819 | _AddStrMethod(message_meta) 820 | _AddSetListenerMethod(message_meta) 821 | _AddByteSizeMethod(message_descriptor, message_meta) 822 | _AddSerializeToStringMethod(message_descriptor, message_meta) 823 | _AddSerializePartialToStringMethod(message_descriptor, message_meta) 824 | _AddMergeFromStringMethod(message_descriptor, message_meta) 825 | _AddIsInitializedMethod(message_descriptor, message_meta) 826 | _AddMergeFromMethod(message_meta) 827 | end 828 | 829 | local function _AddPrivateHelperMethods(message_meta) 830 | local Modified = function (self) 831 | if not self._cached_byte_size_dirty then 832 | self._cached_byte_size_dirty = true 833 | self._listener_for_children.dirty = true 834 | self._is_present_in_parent = true 835 | self._listener:Modified() 836 | end 837 | end 838 | message_meta._member._Modified = Modified 839 | message_meta._member.SetInParent = Modified 840 | end 841 | 842 | local function property_getter(message_meta) 843 | local getter = message_meta._getter 844 | local member = message_meta._member 845 | 846 | return function (self, property) 847 | local g = getter[property] 848 | if g then 849 | return g(self) 850 | else 851 | return member[property] 852 | end 853 | end 854 | end 855 | 856 | local function property_setter(message_meta) 857 | local setter = message_meta._setter 858 | 859 | return function (self, property, value) 860 | local s = setter[property] 861 | if s then 862 | s(self, value) 863 | else 864 | error(property .. " not found") 865 | end 866 | end 867 | end 868 | 869 | function _AddClassAttributesForNestedExtensions(descriptor, message_meta) 870 | local extension_dict = descriptor._extensions_by_name 871 | for extension_name, extension_field in pairs(extension_dict) do 872 | message_meta._member[extension_name] = extension_field 873 | end 874 | end 875 | 876 | local function Message(descriptor) 877 | local message_meta = {} 878 | message_meta._decoders_by_tag = {} 879 | rawset(descriptor, "_extensions_by_name", {}) 880 | for _, k in ipairs(descriptor.extensions) do 881 | descriptor._extensions_by_name[k.name] = k 882 | end 883 | rawset(descriptor, "_extensions_by_number", {}) 884 | for _, k in ipairs(descriptor.extensions) do 885 | descriptor._extensions_by_number[k.number] = k 886 | end 887 | message_meta._descriptor = descriptor 888 | message_meta._extensions_by_name = {} 889 | message_meta._extensions_by_number = {} 890 | 891 | message_meta._getter = {} 892 | message_meta._setter = {} 893 | message_meta._member = {} 894 | -- message_meta._name = descriptor.full_name 895 | 896 | local ns = setmetatable({}, message_meta._member) 897 | message_meta._member.__call = _InitMethod(message_meta) 898 | message_meta._member.__index = message_meta._member 899 | message_meta._member.type = ns 900 | 901 | if rawget(descriptor, "_concrete_class") == nil then 902 | rawset(descriptor, "_concrete_class", ns) 903 | for k, field in ipairs(descriptor.fields) do 904 | _AttachFieldHelpers(message_meta, field) 905 | end 906 | end 907 | _AddEnumValues(descriptor, message_meta) 908 | _AddClassAttributesForNestedExtensions(descriptor, message_meta) 909 | _AddPropertiesForFields(descriptor, message_meta) 910 | _AddPropertiesForExtensions(descriptor, message_meta) 911 | _AddStaticMethods(message_meta) 912 | _AddMessageMethods(descriptor, message_meta) 913 | _AddPrivateHelperMethods(message_meta) 914 | 915 | message_meta.__index = property_getter(message_meta) 916 | message_meta.__newindex = property_setter(message_meta) 917 | 918 | return ns 919 | end 920 | 921 | _M.Message = Message 922 | 923 | --------------------------------------------------------------------------------