/protobuf/protobuf.lua
Lua | 922 lines | 809 code | 93 blank | 20 comment | 114 complexity | 9f718ac50e0a66d1b33fb26ccc94640c MD5 | raw file
- --
- --------------------------------------------------------------------------------
- -- FILE: protobuf.lua
- -- DESCRIPTION: protoc-gen-lua
- -- Google's Protocol Buffers project, ported to lua.
- -- https://code.google.com/p/protoc-gen-lua/
- --
- -- Copyright (c) 2010 , ??? (Zhuoyi Lin) netsnail@gmail.com
- -- All rights reserved.
- --
- -- Use, modification and distribution are subject to the "New BSD License"
- -- as listed at <url: http://www.opensource.org/licenses/bsd-license.php >.
- --
- -- COMPANY: NetEase
- -- CREATED: 2010?07?29? 14?30?02? CST
- --------------------------------------------------------------------------------
- --
- local setmetatable = setmetatable
- local rawset = rawset
- local rawget = rawget
- local error = error
- local ipairs = ipairs
- local pairs = pairs
- local print = print
- local table = table
- local string = string
- local tostring = tostring
- local type = type
- local pb = require "pb"
- local wire_format = require "wire_format"
- local type_checkers = require "type_checkers"
- local encoder = require "encoder"
- local decoder = require "decoder"
- local listener_mod = require "listener"
- local containers = require "containers"
- local descriptor = require "descriptor"
- local FieldDescriptor = descriptor.FieldDescriptor
- local text_format = require "text_format"
- module("protobuf")
- local function make_descriptor(name, descriptor, usable_key)
- local meta = {
- __newindex = function(self, key, value)
- if usable_key[key] then
- rawset(self, key, value)
- else
- error("error key: "..key)
- end
- end
- };
- meta.__index = meta
- meta.__call = function()
- return setmetatable({}, meta)
- end
- _M[name] = setmetatable(descriptor, meta);
- end
- make_descriptor("Descriptor", {}, {
- name = true,
- full_name = true,
- filename = true,
- containing_type = true,
- fields = true,
- nested_types = true,
- enum_types = true,
- extensions = true,
- options = true,
- is_extendable = true,
- extension_ranges = true,
- })
- make_descriptor("FieldDescriptor", FieldDescriptor, {
- name = true,
- full_name = true,
- index = true,
- number = true,
- type = true,
- cpp_type = true,
- label = true,
- has_default_value = true,
- default_value = true,
- containing_type = true,
- message_type = true,
- enum_type = true,
- is_extension = true,
- extension_scope = true,
- })
- make_descriptor("EnumDescriptor", {}, {
- name = true,
- full_name = true,
- values = true,
- containing_type = true,
- options = true
- })
- make_descriptor("EnumValueDescriptor", {}, {
- name = true,
- index = true,
- number = true,
- type = true,
- options = true
- })
- -- Maps from field type to expected wiretype.
- local FIELD_TYPE_TO_WIRE_TYPE = {
- [FieldDescriptor.TYPE_DOUBLE] = wire_format.WIRETYPE_FIXED64,
- [FieldDescriptor.TYPE_FLOAT] = wire_format.WIRETYPE_FIXED32,
- [FieldDescriptor.TYPE_INT64] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_UINT64] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_INT32] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_FIXED64] = wire_format.WIRETYPE_FIXED64,
- [FieldDescriptor.TYPE_FIXED32] = wire_format.WIRETYPE_FIXED32,
- [FieldDescriptor.TYPE_BOOL] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_STRING] = wire_format.WIRETYPE_LENGTH_DELIMITED,
- [FieldDescriptor.TYPE_GROUP] = wire_format.WIRETYPE_START_GROUP,
- [FieldDescriptor.TYPE_MESSAGE] = wire_format.WIRETYPE_LENGTH_DELIMITED,
- [FieldDescriptor.TYPE_BYTES] = wire_format.WIRETYPE_LENGTH_DELIMITED,
- [FieldDescriptor.TYPE_UINT32] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_ENUM] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_SFIXED32] = wire_format.WIRETYPE_FIXED32,
- [FieldDescriptor.TYPE_SFIXED64] = wire_format.WIRETYPE_FIXED64,
- [FieldDescriptor.TYPE_SINT32] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_SINT64] = wire_format.WIRETYPE_VARINT
- }
- local NON_PACKABLE_TYPES = {
- [FieldDescriptor.TYPE_STRING] = true,
- [FieldDescriptor.TYPE_GROUP] = true,
- [FieldDescriptor.TYPE_MESSAGE] = true,
- [FieldDescriptor.TYPE_BYTES] = true
- }
- local _VALUE_CHECKERS = {
- [FieldDescriptor.CPPTYPE_INT32] = type_checkers.Int32ValueChecker(),
- [FieldDescriptor.CPPTYPE_INT64] = type_checkers.Int32ValueChecker(),
- [FieldDescriptor.CPPTYPE_UINT32] = type_checkers.Uint32ValueChecker(),
- [FieldDescriptor.CPPTYPE_UINT64] = type_checkers.Uint32ValueChecker(),
- [FieldDescriptor.CPPTYPE_DOUBLE] = type_checkers.TypeChecker({number = true}),
- [FieldDescriptor.CPPTYPE_FLOAT] = type_checkers.TypeChecker({number = true}),
- [FieldDescriptor.CPPTYPE_BOOL] = type_checkers.TypeChecker({boolean = true, bool = true, int=true}),
- [FieldDescriptor.CPPTYPE_ENUM] = type_checkers.Int32ValueChecker(),
- [FieldDescriptor.CPPTYPE_STRING] = type_checkers.TypeChecker({string = true})
- }
- local TYPE_TO_BYTE_SIZE_FN = {
- [FieldDescriptor.TYPE_DOUBLE] = wire_format.DoubleByteSize,
- [FieldDescriptor.TYPE_FLOAT] = wire_format.FloatByteSize,
- [FieldDescriptor.TYPE_INT64] = wire_format.Int64ByteSize,
- [FieldDescriptor.TYPE_UINT64] = wire_format.UInt64ByteSize,
- [FieldDescriptor.TYPE_INT32] = wire_format.Int32ByteSize,
- [FieldDescriptor.TYPE_FIXED64] = wire_format.Fixed64ByteSize,
- [FieldDescriptor.TYPE_FIXED32] = wire_format.Fixed32ByteSize,
- [FieldDescriptor.TYPE_BOOL] = wire_format.BoolByteSize,
- [FieldDescriptor.TYPE_STRING] = wire_format.StringByteSize,
- [FieldDescriptor.TYPE_GROUP] = wire_format.GroupByteSize,
- [FieldDescriptor.TYPE_MESSAGE] = wire_format.MessageByteSize,
- [FieldDescriptor.TYPE_BYTES] = wire_format.BytesByteSize,
- [FieldDescriptor.TYPE_UINT32] = wire_format.UInt32ByteSize,
- [FieldDescriptor.TYPE_ENUM] = wire_format.EnumByteSize,
- [FieldDescriptor.TYPE_SFIXED32] = wire_format.SFixed32ByteSize,
- [FieldDescriptor.TYPE_SFIXED64] = wire_format.SFixed64ByteSize,
- [FieldDescriptor.TYPE_SINT32] = wire_format.SInt32ByteSize,
- [FieldDescriptor.TYPE_SINT64] = wire_format.SInt64ByteSize
- }
- local TYPE_TO_ENCODER = {
- [FieldDescriptor.TYPE_DOUBLE] = encoder.DoubleEncoder,
- [FieldDescriptor.TYPE_FLOAT] = encoder.FloatEncoder,
- [FieldDescriptor.TYPE_INT64] = encoder.Int64Encoder,
- [FieldDescriptor.TYPE_UINT64] = encoder.UInt64Encoder,
- [FieldDescriptor.TYPE_INT32] = encoder.Int32Encoder,
- [FieldDescriptor.TYPE_FIXED64] = encoder.Fixed64Encoder,
- [FieldDescriptor.TYPE_FIXED32] = encoder.Fixed32Encoder,
- [FieldDescriptor.TYPE_BOOL] = encoder.BoolEncoder,
- [FieldDescriptor.TYPE_STRING] = encoder.StringEncoder,
- [FieldDescriptor.TYPE_GROUP] = encoder.GroupEncoder,
- [FieldDescriptor.TYPE_MESSAGE] = encoder.MessageEncoder,
- [FieldDescriptor.TYPE_BYTES] = encoder.BytesEncoder,
- [FieldDescriptor.TYPE_UINT32] = encoder.UInt32Encoder,
- [FieldDescriptor.TYPE_ENUM] = encoder.EnumEncoder,
- [FieldDescriptor.TYPE_SFIXED32] = encoder.SFixed32Encoder,
- [FieldDescriptor.TYPE_SFIXED64] = encoder.SFixed64Encoder,
- [FieldDescriptor.TYPE_SINT32] = encoder.SInt32Encoder,
- [FieldDescriptor.TYPE_SINT64] = encoder.SInt64Encoder
- }
- local TYPE_TO_SIZER = {
- [FieldDescriptor.TYPE_DOUBLE] = encoder.DoubleSizer,
- [FieldDescriptor.TYPE_FLOAT] = encoder.FloatSizer,
- [FieldDescriptor.TYPE_INT64] = encoder.Int64Sizer,
- [FieldDescriptor.TYPE_UINT64] = encoder.UInt64Sizer,
- [FieldDescriptor.TYPE_INT32] = encoder.Int32Sizer,
- [FieldDescriptor.TYPE_FIXED64] = encoder.Fixed64Sizer,
- [FieldDescriptor.TYPE_FIXED32] = encoder.Fixed32Sizer,
- [FieldDescriptor.TYPE_BOOL] = encoder.BoolSizer,
- [FieldDescriptor.TYPE_STRING] = encoder.StringSizer,
- [FieldDescriptor.TYPE_GROUP] = encoder.GroupSizer,
- [FieldDescriptor.TYPE_MESSAGE] = encoder.MessageSizer,
- [FieldDescriptor.TYPE_BYTES] = encoder.BytesSizer,
- [FieldDescriptor.TYPE_UINT32] = encoder.UInt32Sizer,
- [FieldDescriptor.TYPE_ENUM] = encoder.EnumSizer,
- [FieldDescriptor.TYPE_SFIXED32] = encoder.SFixed32Sizer,
- [FieldDescriptor.TYPE_SFIXED64] = encoder.SFixed64Sizer,
- [FieldDescriptor.TYPE_SINT32] = encoder.SInt32Sizer,
- [FieldDescriptor.TYPE_SINT64] = encoder.SInt64Sizer
- }
- local TYPE_TO_DECODER = {
- [FieldDescriptor.TYPE_DOUBLE] = decoder.DoubleDecoder,
- [FieldDescriptor.TYPE_FLOAT] = decoder.FloatDecoder,
- [FieldDescriptor.TYPE_INT64] = decoder.Int64Decoder,
- [FieldDescriptor.TYPE_UINT64] = decoder.UInt64Decoder,
- [FieldDescriptor.TYPE_INT32] = decoder.Int32Decoder,
- [FieldDescriptor.TYPE_FIXED64] = decoder.Fixed64Decoder,
- [FieldDescriptor.TYPE_FIXED32] = decoder.Fixed32Decoder,
- [FieldDescriptor.TYPE_BOOL] = decoder.BoolDecoder,
- [FieldDescriptor.TYPE_STRING] = decoder.StringDecoder,
- [FieldDescriptor.TYPE_GROUP] = decoder.GroupDecoder,
- [FieldDescriptor.TYPE_MESSAGE] = decoder.MessageDecoder,
- [FieldDescriptor.TYPE_BYTES] = decoder.BytesDecoder,
- [FieldDescriptor.TYPE_UINT32] = decoder.UInt32Decoder,
- [FieldDescriptor.TYPE_ENUM] = decoder.EnumDecoder,
- [FieldDescriptor.TYPE_SFIXED32] = decoder.SFixed32Decoder,
- [FieldDescriptor.TYPE_SFIXED64] = decoder.SFixed64Decoder,
- [FieldDescriptor.TYPE_SINT32] = decoder.SInt32Decoder,
- [FieldDescriptor.TYPE_SINT64] = decoder.SInt64Decoder
- }
- local FIELD_TYPE_TO_WIRE_TYPE = {
- [FieldDescriptor.TYPE_DOUBLE] = wire_format.WIRETYPE_FIXED64,
- [FieldDescriptor.TYPE_FLOAT] = wire_format.WIRETYPE_FIXED32,
- [FieldDescriptor.TYPE_INT64] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_UINT64] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_INT32] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_FIXED64] = wire_format.WIRETYPE_FIXED64,
- [FieldDescriptor.TYPE_FIXED32] = wire_format.WIRETYPE_FIXED32,
- [FieldDescriptor.TYPE_BOOL] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_STRING] = wire_format.WIRETYPE_LENGTH_DELIMITED,
- [FieldDescriptor.TYPE_GROUP] = wire_format.WIRETYPE_START_GROUP,
- [FieldDescriptor.TYPE_MESSAGE] = wire_format.WIRETYPE_LENGTH_DELIMITED,
- [FieldDescriptor.TYPE_BYTES] = wire_format.WIRETYPE_LENGTH_DELIMITED,
- [FieldDescriptor.TYPE_UINT32] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_ENUM] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_SFIXED32] = wire_format.WIRETYPE_FIXED32,
- [FieldDescriptor.TYPE_SFIXED64] = wire_format.WIRETYPE_FIXED64,
- [FieldDescriptor.TYPE_SINT32] = wire_format.WIRETYPE_VARINT,
- [FieldDescriptor.TYPE_SINT64] = wire_format.WIRETYPE_VARINT
- }
- local function IsTypePackable(field_type)
- return NON_PACKABLE_TYPES[field_type] == nil
- end
- local function GetTypeChecker(cpp_type, field_type)
- if (cpp_type == FieldDescriptor.CPPTYPE_STRING and field_type == FieldDescriptor.TYPE_STRING) then
- return type_checkers.UnicodeValueChecker()
- end
- return _VALUE_CHECKERS[cpp_type]
- end
- local function _DefaultValueConstructorForField(field)
- if field.label == FieldDescriptor.LABEL_REPEATED then
- if type(field.default_value) ~= "table" or #(field.default_value) ~= 0 then
- error('Repeated field default value not empty list:' .. tostring(field.default_value))
- end
- if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- local message_type = field.message_type
- return function (message)
- return containers.RepeatedCompositeFieldContainer(message._listener_for_children, message_type)
- end
- else
- local type_checker = GetTypeChecker(field.cpp_type, field.type)
- return function (message)
- return containers.RepeatedScalarFieldContainer(message._listener_for_children, type_checker)
- end
- end
- end
- if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- local message_type = field.message_type
- return function (message)
- result = message_type._concrete_class()
- result._SetListener(message._listener_for_children)
- return result
- end
- end
- return function (message)
- return field.default_value
- end
- end
- local function _AttachFieldHelpers(message_meta, field_descriptor)
- local is_repeated = (field_descriptor.label == FieldDescriptor.LABEL_REPEATED)
- local is_packed = (field_descriptor.has_options and field_descriptor.GetOptions().packed)
- rawset(field_descriptor, "_encoder", TYPE_TO_ENCODER[field_descriptor.type](field_descriptor.number, is_repeated, is_packed))
- rawset(field_descriptor, "_sizer", TYPE_TO_SIZER[field_descriptor.type](field_descriptor.number, is_repeated, is_packed))
- rawset(field_descriptor, "_default_constructor", _DefaultValueConstructorForField(field_descriptor))
- local AddDecoder = function(wiretype, is_packed)
- local tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
- 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)
- end
-
- AddDecoder(FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], False)
- if is_repeated and IsTypePackable(field_descriptor.type) then
- AddDecoder(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
- end
- end
- local function _AddEnumValues(descriptor, message_meta)
- for _, enum_type in ipairs(descriptor.enum_types) do
- for _, enum_value in ipairs(enum_type.values) do
- message_meta._member[enum_value.name] = enum_value.number
- end
- end
- end
- local function _InitMethod(message_meta)
- return function()
- local self = {}
- self._cached_byte_size = 0
- self._cached_byte_size_dirty = false
- self._fields = {}
- self._is_present_in_parent = false
- self._listener = listener_mod.NullMessageListener()
- self._listener_for_children = listener_mod.Listener(self)
- return setmetatable(self, message_meta)
- end
- end
- local function _AddPropertiesForRepeatedField(field, message_meta)
- local property_name = field.name
- message_meta._getter[property_name] = function(self)
- local field_value = self._fields[field]
- if field_value == nil then
- field_value = field._default_constructor(self)
- self._fields[field] = field_value
- end
- return field_value
- end
- message_meta._setter[property_name] = function(self)
- error('Assignment not allowed to repeated field "' .. property_name .. '" in protocol message object.')
- end
- end
- local function _AddPropertiesForNonRepeatedCompositeField(field, message_meta)
- local property_name = field.name
- local message_type = field.message_type
- message_meta._getter[property_name] = function(self)
- local field_value = self._fields[field]
- if field_value == nil then
- field_value = message_type._concrete_class()
- field_value:_SetListener(self._listener_for_children)
-
- self._fields[field] = field_value
- end
- return field_value
- end
- message_meta._setter[property_name] = function(self, new_value)
- error('Assignment not allowed to composite field' .. property_name .. 'in protocol message object.' )
- end
- end
- local function _AddPropertiesForNonRepeatedScalarField(field, message)
- local property_name = field.name
- local type_checker = GetTypeChecker(field.cpp_type, field.type)
- local default_value = field.default_value
- message._getter[property_name] = function(self)
- local value = self._fields[field]
- if value ~= nil then
- return self._fields[field]
- else
- return default_value
- end
- end
- message._setter[property_name] = function(self, new_value)
- type_checker(new_value)
- self._fields[field] = new_value
- if not self._cached_byte_size_dirty then
- message._member._Modified(self)
- end
- end
- end
- local function _AddPropertiesForField(field, message_meta)
- constant_name = field.name:upper() .. "_FIELD_NUMBER"
- message_meta._member[constant_name] = field.number
- if field.label == FieldDescriptor.LABEL_REPEATED then
- _AddPropertiesForRepeatedField(field, message_meta)
- elseif field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- _AddPropertiesForNonRepeatedCompositeField(field, message_meta)
- else
- _AddPropertiesForNonRepeatedScalarField(field, message_meta)
- end
- end
- local _ED_meta = {
- __index = function(self, extension_handle)
- local _extended_message = rawget(self, "_extended_message")
- local value = _extended_message._fields[extension_handle]
- if value ~= nil then
- return value
- end
- if extension_handle.label == FieldDescriptor.LABEL_REPEATED then
- value = extension_handle._default_constructor(self._extended_message)
- elseif extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- value = extension_handle.message_type._concrete_class()
- value:_SetListener(_extended_message._listener_for_children)
- else
- return extension_handle.default_value
- end
- _extended_message._fields[extension_handle] = value
- return value
- end,
- __newindex = function(self, extension_handle, value)
- local _extended_message = rawget(self, "_extended_message")
- if (extension_handle.label == FieldDescriptor.LABEL_REPEATED or
- extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE) then
- error('Cannot assign to extension "'.. extension_handle.full_name .. '" because it is a repeated or composite type.')
- end
- local type_checker = GetTypeChecker(extension_handle.cpp_type, extension_handle.type)
- type_checker.CheckValue(value)
- _extended_message._fields[extension_handle] = value
- _extended_message._Modified()
- end
- }
- local function _ExtensionDict(message)
- local o = {}
- o._extended_message = message
- return setmetatable(o, _ED_meta)
- end
- local function _AddPropertiesForFields(descriptor, message_meta)
- for _, field in ipairs(descriptor.fields) do
- _AddPropertiesForField(field, message_meta)
- end
- if descriptor.is_extendable then
- message_meta._getter.Extensions = function(self) return _ExtensionDict(self) end
- end
- end
- local function _AddPropertiesForExtensions(descriptor, message_meta)
- local extension_dict = descriptor._extensions_by_name
- for extension_name, extension_field in pairs(extension_dict) do
- local constant_name = string.upper(extension_name) .. "_FIELD_NUMBER"
- message_meta._member[constant_name] = extension_field.number
- end
- end
- local function _AddStaticMethods(message_meta)
- message_meta._member.RegisterExtension = function(extension_handle)
- extension_handle.containing_type = message_meta._descriptor
- _AttachFieldHelpers(message_meta, extension_handle)
- if message_meta._extensions_by_number[extension_handle.number] == nil then
- message_meta._extensions_by_number[extension_handle.number] = extension_handle
- else
- error(
- string.format('Extensions "%s" and "%s" both try to extend message type "%s" with field number %d.',
- extension_handle.full_name, actual_handle.full_name,
- message_meta._descriptor.full_name, extension_handle.number))
- end
- message_meta._extensions_by_name[extension_handle.full_name] = extension_handle
- end
- message_meta._member.FromString = function(s)
- local message = message_meta._member.__call()
- message.MergeFromString(s)
- return message
- end
- end
- local function _IsPresent(descriptor, value)
- if descriptor.label == FieldDescriptor.LABEL_REPEATED then
- return value
- elseif descriptor.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- return value._is_present_in_parent
- else
- return true
- end
- end
- local function _AddListFieldsMethod(message_descriptor, message_meta)
- message_meta._member.ListFields = function (self)
- local list_field = function(fields)
- local f, s, v = pairs(self._fields)
- local iter = function(a, i)
- while true do
- local descriptor, value = f(a, i)
- if descriptor == nil then
- return
- elseif _IsPresent(descriptor, value) then
- return descriptor, value
- end
- end
- end
- return iter, s, v
- end
- return list_field(self._fields)
- end
- end
- local function _AddHasFieldMethod(message_descriptor, message_meta)
- local singular_fields = {}
- for _, field in ipairs(message_descriptor.fields) do
- if field.label ~= FieldDescriptor.LABEL_REPEATED then
- singular_fields[field.name] = field
- end
- end
- message_meta._member.HasField = function (self, field_name)
- field = singular_fields[field_name]
- if feild == nil then
- error('Protocol message has no singular "'.. field_name.. '" field.')
- end
- if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- value = self._fields[field]
- return value ~= nil and value._is_present_in_parent
- else
- return self._fields[field]
- end
- end
- end
- local function _AddClearFieldMethod(message_descriptor, message_meta)
- message_meta._member.ClearField = function(self, field_name)
- if message_descriptor.fields_by_name[field_name] == nil then
- error('Protocol message has no "' .. field_name .. '" field.')
- end
- if self._fields[field] then
- self._fields[field] = nil
- end
- message_meta._member._Modified(self)
- end
- end
- local function _AddClearExtensionMethod(message_meta)
- message_meta._member.ClearExtension = function(self, extension_handle)
- if self._fields[extension_handle] == nil then
- self._fields[extension_handle] = nil
- end
- message_meta._member._Modified(self)
- end
- end
- local function _AddClearMethod(message_descriptor, message_meta)
- message_meta._member.Clear = function(self)
- self._fields = {}
- message_meta._member._Modified(self)
- end
- end
- local function _AddStrMethod(message_meta)
- local format = text_format.msg_format
- message_meta.__tostring = function(self)
- return format(self)
- end
- end
- local function _AddHasExtensionMethod(message_meta)
- message_meta._member.HasExtension = function(self, extension_handle)
- if extension_handle.label == FieldDescriptor.LABEL_REPEATED then
- error(extension_handle.full_name .. ' is repeated.')
- end
- if extension_handle.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- value = self._fields[extension_handle]
- return value ~= nil and value._is_present_in_parent
- else
- return self._fields[extension_handle]
- end
- end
- end
- local function _AddSetListenerMethod(message_meta)
- message_meta._member._SetListener = function(self, listener)
- if listener ~= nil then
- self._listener = listener_mod.NullMessageListener()
- else
- self._listener = listener
- end
- end
- end
- local function _AddByteSizeMethod(message_descriptor, message_meta)
- message_meta._member.ByteSize = function(self)
- if not self._cached_byte_size_dirty then
- return self._cached_byte_size
- end
- local size = 0
- for field_descriptor, field_value in message_meta._member.ListFields(self) do
- size = field_descriptor._sizer(field_value) + size
- end
- self._cached_byte_size = size
- self._cached_byte_size_dirty = false
- self._listener_for_children.dirty = false
- return size
- end
- end
- local function _AddSerializeToStringMethod(message_descriptor, message_meta)
- message_meta._member.SerializeToString = function(self)
- if not message_meta._member.IsInitialized(self) then
- error('Message is missing required fields: ' ..
- table.concat(message_meta._member.FindInitializationErrors(self), ','))
- end
- return message_meta._member.SerializePartialToString(self)
- end
- message_meta._member.SerializeToIOString = function(self, iostring)
- if not message_meta._member.IsInitialized(self) then
- error('Message is missing required fields: ' ..
- table.concat(message_meta._member.FindInitializationErrors(self), ','))
- end
- return message_meta._member.SerializePartialToIOString(self, iostring)
- end
- end
- local function _AddSerializePartialToStringMethod(message_descriptor, message_meta)
- local concat = table.concat
- local _internal_serialize = function(self, write_bytes)
- for field_descriptor, field_value in message_meta._member.ListFields(self) do
- field_descriptor._encoder(write_bytes, field_value)
- end
- end
- local _serialize_partial_to_iostring = function(self, iostring)
- local w = iostring.write
- local write = function(value)
- w(iostring, value)
- end
- _internal_serialize(self, write)
- return
- end
- local _serialize_partial_to_string = function(self)
- local out = {}
- local write = function(value)
- out[#out + 1] = value
- end
- _internal_serialize(self, write)
- return concat(out)
- end
- message_meta._member._InternalSerialize = _internal_serialize
- message_meta._member.SerializePartialToIOString = _serialize_partial_to_iostring
- message_meta._member.SerializePartialToString = _serialize_partial_to_string
- end
- local function _AddMergeFromStringMethod(message_descriptor, message_meta)
- local ReadTag = decoder.ReadTag
- local SkipField = decoder.SkipField
- local decoders_by_tag = message_meta._decoders_by_tag
- local _internal_parse = function(self, buffer, pos, pend)
- message_meta._member._Modified(self)
- local field_dict = self._fields
- local tag_bytes, new_pos
- local field_decoder
- while pos ~= pend do
- tag_bytes, new_pos = ReadTag(buffer, pos)
- field_decoder = decoders_by_tag[tag_bytes]
- if field_decoder == nil then
- new_pos = SkipField(buffer, new_pos, pend, tag_bytes)
- if new_pos == -1 then
- return pos
- end
- pos = new_pos
- else
- pos = field_decoder(buffer, new_pos, pend, self, field_dict)
- end
- end
- return pos
- end
- message_meta._member._InternalParse = _internal_parse
- local merge_from_string = function(self, serialized)
- local length = #serialized
- if _internal_parse(self, serialized, 0, length) ~= length then
- error('Unexpected end-group tag.')
- end
- return length
- end
- message_meta._member.MergeFromString = merge_from_string
- message_meta._member.ParseFromString = function(self, serialized)
- message_meta._member.Clear(self)
- merge_from_string(self, serialized)
- end
- end
- local function _AddIsInitializedMethod(message_descriptor, message_meta)
- local required_fields = {}
- for _, field in ipairs(message_descriptor.fields) do
- if field.label == FieldDescriptor.LABEL_REQUIRED then
- required_fields[#required_fields + 1] = field
- end
- end
- message_meta._member.IsInitialized = function(self, errors)
- for _, field in ipairs(required_fields) do
- if self._fields[field] == nil or
- (field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE and not self._fields[field]._is_present_in_parent) then
- if errors ~= nil then
- errors[#errors + 1] = message_meta._member.FindInitializationErrors(self)
- end
- return false
- end
- end
- for field, value in pairs(self._fields) do
- if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- if field.label == FieldDescriptor.LABEL_REPEATED then
- for _, element in ipairs(value) do
- if not element:IsInitialized() then
- if errors ~= nil then
- errors[#errors + 1] = message_meta._member.FindInitializationErrors(self)
- end
- return false
- end
- end
- elseif value._is_present_in_parent and not value:IsInitialized() then
- if errors ~= nil then
- errors[#errors + 1] = message_meta._member.FindInitializationErrors(self)
- end
- return false
- end
- end
- end
- return true
- end
- message_meta._member.FindInitializationErrors = function(self)
- local errors = {}
- for _,field in ipairs(required_fields) do
- if not message_meta._member.HasField(self, field.name) then
- errors.append(field.name)
- end
- end
- for field, value in message_meta._member.ListFields(self) do
- if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE then
- if field.is_extension then
- name = io:format("(%s)", field.full_name)
- else
- name = field.name
- end
- if field.label == FieldDescriptor.LABEL_REPEATED then
- for i, element in ipairs(value) do
- prefix = io:format("%s[%d].", name, i)
- sub_errors = element:FindInitializationErrors()
- for _, e in ipairs(sub_errors) do
- errors[#errors + 1] = prefix .. e
- end
- end
- else
- prefix = name .. "."
- sub_errors = value:FindInitializationErrors()
- for _, e in ipairs(sub_errors) do
- errors[#errors + 1] = prefix .. e
- end
- end
- end
- end
- return errors
- end
- end
- local function _AddMergeFromMethod(message_meta)
- local LABEL_REPEATED = FieldDescriptor.LABEL_REPEATED
- local CPPTYPE_MESSAGE = FieldDescriptor.CPPTYPE_MESSAGE
- message_meta._member.MergeFrom = function (self, msg)
- assert(msg ~= self)
- message_meta._member._Modified(self)
- local fields = self._fields
- for field, value in pairs(msg._fields) do
- if field.label == LABEL_REPEATED or field.cpp_type == CPPTYPE_MESSAGE then
- field_value = fields[field]
- if field_value == nil then
- field_value = field._default_constructor(self)
- fields[field] = field_value
- end
- field_value:MergeFrom(value)
- else
- self._fields[field] = value
- end
- end
- end
- end
- local function _AddMessageMethods(message_descriptor, message_meta)
- _AddListFieldsMethod(message_descriptor, message_meta)
- _AddHasFieldMethod(message_descriptor, message_meta)
- _AddClearFieldMethod(message_descriptor, message_meta)
- if message_descriptor.is_extendable then
- _AddClearExtensionMethod(message_meta)
- _AddHasExtensionMethod(message_meta)
- end
- _AddClearMethod(message_descriptor, message_meta)
- -- _AddEqualsMethod(message_descriptor, message_meta)
- _AddStrMethod(message_meta)
- _AddSetListenerMethod(message_meta)
- _AddByteSizeMethod(message_descriptor, message_meta)
- _AddSerializeToStringMethod(message_descriptor, message_meta)
- _AddSerializePartialToStringMethod(message_descriptor, message_meta)
- _AddMergeFromStringMethod(message_descriptor, message_meta)
- _AddIsInitializedMethod(message_descriptor, message_meta)
- _AddMergeFromMethod(message_meta)
- end
- local function _AddPrivateHelperMethods(message_meta)
- local Modified = function (self)
- if not self._cached_byte_size_dirty then
- self._cached_byte_size_dirty = true
- self._listener_for_children.dirty = true
- self._is_present_in_parent = true
- self._listener:Modified()
- end
- end
- message_meta._member._Modified = Modified
- message_meta._member.SetInParent = Modified
- end
- local function property_getter(message_meta)
- local getter = message_meta._getter
- local member = message_meta._member
-
- return function (self, property)
- local g = getter[property]
- if g then
- return g(self)
- else
- return member[property]
- end
- end
- end
- local function property_setter(message_meta)
- local setter = message_meta._setter
- return function (self, property, value)
- local s = setter[property]
- if s then
- s(self, value)
- else
- error(property .. " not found")
- end
- end
- end
- function _AddClassAttributesForNestedExtensions(descriptor, message_meta)
- local extension_dict = descriptor._extensions_by_name
- for extension_name, extension_field in pairs(extension_dict) do
- message_meta._member[extension_name] = extension_field
- end
- end
- local function Message(descriptor)
- local message_meta = {}
- message_meta._decoders_by_tag = {}
- rawset(descriptor, "_extensions_by_name", {})
- for _, k in ipairs(descriptor.extensions) do
- descriptor._extensions_by_name[k.name] = k
- end
- rawset(descriptor, "_extensions_by_number", {})
- for _, k in ipairs(descriptor.extensions) do
- descriptor._extensions_by_number[k.number] = k
- end
- message_meta._descriptor = descriptor
- message_meta._extensions_by_name = {}
- message_meta._extensions_by_number = {}
- message_meta._getter = {}
- message_meta._setter = {}
- message_meta._member = {}
- -- message_meta._name = descriptor.full_name
- local ns = setmetatable({}, message_meta._member)
- message_meta._member.__call = _InitMethod(message_meta)
- message_meta._member.__index = message_meta._member
- message_meta._member.type = ns
- if rawget(descriptor, "_concrete_class") == nil then
- rawset(descriptor, "_concrete_class", ns)
- for k, field in ipairs(descriptor.fields) do
- _AttachFieldHelpers(message_meta, field)
- end
- end
- _AddEnumValues(descriptor, message_meta)
- _AddClassAttributesForNestedExtensions(descriptor, message_meta)
- _AddPropertiesForFields(descriptor, message_meta)
- _AddPropertiesForExtensions(descriptor, message_meta)
- _AddStaticMethods(message_meta)
- _AddMessageMethods(descriptor, message_meta)
- _AddPrivateHelperMethods(message_meta)
- message_meta.__index = property_getter(message_meta)
- message_meta.__newindex = property_setter(message_meta)
- return ns
- end
- _M.Message = Message