// Protocol Buffers - Google's data interchange format // Copyright 2008 Google Inc. All rights reserved. // https://developers.google.com/protocol-buffers/ // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // * Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above // copyright notice, this list of conditions and the following disclaimer // in the documentation and/or other materials provided with the // distribution. // * Neither the name of Google Inc. nor the names of its // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Author: kenton@google.com (Kenton Varda) // Based on original Protocol Buffers design by // Sanjay Ghemawat, Jeff Dean, and others. #include #include #include #include #include #include #include #include #include #include #include #include #include // Must be included last #include PROTOBUF_PRAGMA_INIT_SEG namespace google { namespace protobuf { namespace internal { void DestroyMessage(const void* message) { static_cast(message)->~MessageLite(); } void DestroyString(const void* s) { static_cast(s)->~basic_string(); } PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY ExplicitlyConstructed fixed_address_empty_string{}; // NOLINT PROTOBUF_CONSTINIT std::atomic init_protobuf_defaults_state{false}; static bool InitProtobufDefaultsImpl() { fixed_address_empty_string.DefaultConstruct(); OnShutdownDestroyString(fixed_address_empty_string.get_mutable()); init_protobuf_defaults_state.store(true, std::memory_order_release); return true; } void InitProtobufDefaultsSlow() { static bool is_inited = InitProtobufDefaultsImpl(); (void)is_inited; } // Force the initialization of the empty string. // Normally, registration would do it, but we don't have any guarantee that // there is any object with reflection. PROTOBUF_ATTRIBUTE_INIT_PRIORITY static std::true_type init_empty_string = (InitProtobufDefaultsSlow(), std::true_type{}); size_t StringSpaceUsedExcludingSelfLong(const std::string& str) { const void* start = &str; const void* end = &str + 1; if (start <= str.data() && str.data() < end) { // The string's data is stored inside the string object itself. return 0; } else { return str.capacity(); } } template const T& Get(const void* ptr) { return *static_cast(ptr); } // PrimitiveTypeHelper is a wrapper around the interface of WireFormatLite. // WireFormatLite has a very inconvenient interface with respect to template // meta-programming. This class wraps the different named functions into // a single Serialize / SerializeToArray interface. template struct PrimitiveTypeHelper; template <> struct PrimitiveTypeHelper { typedef bool Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteBoolNoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteBoolNoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef int32_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteInt32NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteInt32NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef int32_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteSInt32NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteSInt32NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef uint32_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteUInt32NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteUInt32NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef int64_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteInt64NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteInt64NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef int64_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteSInt64NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteSInt64NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef uint64_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteUInt64NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteUInt64NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef uint32_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteFixed32NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteFixed32NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper { typedef uint64_t Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { WireFormatLite::WriteFixed64NoTag(Get(ptr), output); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { return WireFormatLite::WriteFixed64NoTagToArray(Get(ptr), buffer); } }; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper {}; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper { typedef int32_t Type; }; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper { typedef int64_t Type; }; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper { typedef float Type; }; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper { typedef double Type; }; template <> struct PrimitiveTypeHelper { typedef std::string Type; static void Serialize(const void* ptr, io::CodedOutputStream* output) { const Type& value = *static_cast(ptr); output->WriteVarint32(value.size()); output->WriteRawMaybeAliased(value.data(), value.size()); } static uint8_t* SerializeToArray(const void* ptr, uint8_t* buffer) { const Type& value = *static_cast(ptr); return io::CodedOutputStream::WriteStringWithSizeToArray(value, buffer); } }; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper {}; template <> struct PrimitiveTypeHelper : PrimitiveTypeHelper {}; // We want to serialize to both CodedOutputStream and directly into byte arrays // without duplicating the code. In fact we might want extra output channels in // the future. template struct OutputHelper; template void SerializeTo(const void* ptr, O* output) { OutputHelper::Serialize(ptr, output); } template void WriteTagTo(uint32_t tag, O* output) { SerializeTo(&tag, output); } template void WriteLengthTo(uint32_t length, O* output) { SerializeTo(&length, output); } // Specialization for coded output stream template struct OutputHelper { static void Serialize(const void* ptr, io::CodedOutputStream* output) { PrimitiveTypeHelper::Serialize(ptr, output); } }; // Specialization for writing into a plain array struct ArrayOutput { uint8_t* ptr; bool is_deterministic; }; template struct OutputHelper { static void Serialize(const void* ptr, ArrayOutput* output) { output->ptr = PrimitiveTypeHelper::SerializeToArray(ptr, output->ptr); } }; void SerializeMessageNoTable(const MessageLite* msg, io::CodedOutputStream* output) { msg->SerializeWithCachedSizes(output); } void SerializeMessageNoTable(const MessageLite* msg, ArrayOutput* output) { io::ArrayOutputStream array_stream(output->ptr, INT_MAX); io::CodedOutputStream o(&array_stream); o.SetSerializationDeterministic(output->is_deterministic); msg->SerializeWithCachedSizes(&o); output->ptr += o.ByteCount(); } // Helper to branch to fast path if possible void SerializeMessageDispatch(const MessageLite& msg, const FieldMetadata* field_table, int num_fields, int32_t /*cached_size*/, io::CodedOutputStream* output) { const uint8_t* base = reinterpret_cast(&msg); SerializeInternal(base, field_table, num_fields, output); } // Helper to branch to fast path if possible void SerializeMessageDispatch(const MessageLite& msg, const FieldMetadata* field_table, int num_fields, int32_t /*cached_size*/, ArrayOutput* output) { const uint8_t* base = reinterpret_cast(&msg); output->ptr = SerializeInternalToArray(base, field_table, num_fields, output->is_deterministic, output->ptr); } // Serializing messages is special as it's not a primitive type and needs an // explicit overload for each output type. template void SerializeMessageTo(const MessageLite* msg, const void* table_ptr, O* output) { const SerializationTable* table = static_cast(table_ptr); if (!table) { // Proto1 WriteLengthTo(msg->GetCachedSize(), output); SerializeMessageNoTable(msg, output); return; } const FieldMetadata* field_table = table->field_table; const uint8_t* base = reinterpret_cast(msg); int cached_size = *reinterpret_cast(base + field_table->offset); WriteLengthTo(cached_size, output); int num_fields = table->num_fields - 1; SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size, output); } // Almost the same as above only it doesn't output the length field. template void SerializeGroupTo(const MessageLite* msg, const void* table_ptr, O* output) { const SerializationTable* table = static_cast(table_ptr); if (!table) { // Proto1 SerializeMessageNoTable(msg, output); return; } const FieldMetadata* field_table = table->field_table; const uint8_t* base = reinterpret_cast(msg); int cached_size = *reinterpret_cast(base + field_table->offset); int num_fields = table->num_fields - 1; SerializeMessageDispatch(*msg, field_table + 1, num_fields, cached_size, output); } template struct SingularFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { WriteTagTo(md.tag, output); SerializeTo(field, output); } }; template <> struct SingularFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { WriteTagTo(md.tag, output); SerializeTo(&Get(field).Get(), output); } }; template <> struct SingularFieldHelper : SingularFieldHelper {}; template <> struct SingularFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { WriteTagTo(md.tag, output); SerializeGroupTo(Get(field), static_cast(md.ptr), output); WriteTagTo(md.tag + 1, output); } }; template <> struct SingularFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { WriteTagTo(md.tag, output); SerializeMessageTo(Get(field), static_cast(md.ptr), output); } }; template <> struct SingularFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { WriteTagTo(md.tag, output); SerializeTo(&Get(field), output); } }; template struct RepeatedFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { typedef typename PrimitiveTypeHelper::Type T; const RepeatedField& array = Get >(field); for (int i = 0; i < array.size(); i++) { WriteTagTo(md.tag, output); SerializeTo(&array[i], output); } } }; // We need to use a helper class to get access to the private members class AccessorHelper { public: static int Size(const RepeatedPtrFieldBase& x) { return x.size(); } static void const* Get(const RepeatedPtrFieldBase& x, int idx) { return x.raw_data()[idx]; } }; template <> struct RepeatedFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { const internal::RepeatedPtrFieldBase& array = Get(field); for (int i = 0; i < AccessorHelper::Size(array); i++) { WriteTagTo(md.tag, output); SerializeTo(AccessorHelper::Get(array, i), output); } } }; template <> struct RepeatedFieldHelper : RepeatedFieldHelper {}; template <> struct RepeatedFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { const internal::RepeatedPtrFieldBase& array = Get(field); for (int i = 0; i < AccessorHelper::Size(array); i++) { WriteTagTo(md.tag, output); SerializeGroupTo( static_cast(AccessorHelper::Get(array, i)), static_cast(md.ptr), output); WriteTagTo(md.tag + 1, output); } } }; template <> struct RepeatedFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { const internal::RepeatedPtrFieldBase& array = Get(field); for (int i = 0; i < AccessorHelper::Size(array); i++) { WriteTagTo(md.tag, output); SerializeMessageTo( static_cast(AccessorHelper::Get(array, i)), md.ptr, output); } } }; template <> struct RepeatedFieldHelper : RepeatedFieldHelper {}; template struct PackedFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { typedef typename PrimitiveTypeHelper::Type T; const RepeatedField& array = Get >(field); if (array.empty()) return; WriteTagTo(md.tag, output); int cached_size = Get(static_cast(field) + sizeof(RepeatedField)); WriteLengthTo(cached_size, output); for (int i = 0; i < array.size(); i++) { SerializeTo(&array[i], output); } } }; template <> struct PackedFieldHelper { template static void Serialize(const void* /*field*/, const FieldMetadata& md, O* /*output*/) { GOOGLE_LOG(FATAL) << "Not implemented field number " << md.tag << " with type " << md.type; } }; template <> struct PackedFieldHelper : PackedFieldHelper {}; template <> struct PackedFieldHelper : PackedFieldHelper {}; template <> struct PackedFieldHelper : PackedFieldHelper {}; template <> struct PackedFieldHelper : PackedFieldHelper {}; template struct OneOfFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { SingularFieldHelper::Serialize(field, md, output); } }; template <> struct OneOfFieldHelper { template static void Serialize(const void* field, const FieldMetadata& md, O* output) { SingularFieldHelper::Serialize( Get(field), md, output); } }; void SerializeNotImplemented(int field) { GOOGLE_LOG(FATAL) << "Not implemented field number " << field; } // When switching to c++11 we should make these constexpr functions #define SERIALIZE_TABLE_OP(type, type_class) \ ((type - 1) + static_cast(type_class) * FieldMetadata::kNumTypes) int FieldMetadata::CalculateType(int type, FieldMetadata::FieldTypeClass type_class) { return SERIALIZE_TABLE_OP(type, type_class); } template bool IsNull(const void* ptr) { return *static_cast::Type*>(ptr) == 0; } template <> bool IsNull(const void* ptr) { return static_cast(ptr)->Get().size() == 0; } template <> bool IsNull(const void* ptr) { return static_cast(ptr)->Get().size() == 0; } template <> bool IsNull(const void* ptr) { return Get(ptr) == nullptr; } template <> bool IsNull(const void* ptr) { return Get(ptr) == nullptr; } template <> bool IsNull(const void* ptr) { return static_cast(ptr)->empty(); } #define SERIALIZERS_FOR_TYPE(type) \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kPresence): \ if (!IsPresent(base, field_metadata.has_offset)) continue; \ SingularFieldHelper::Serialize(ptr, field_metadata, output); \ break; \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kNoPresence): \ if (IsNull(ptr)) continue; \ SingularFieldHelper::Serialize(ptr, field_metadata, output); \ break; \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kRepeated): \ RepeatedFieldHelper::Serialize(ptr, field_metadata, output); \ break; \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kPacked): \ PackedFieldHelper::Serialize(ptr, field_metadata, output); \ break; \ case SERIALIZE_TABLE_OP(type, FieldMetadata::kOneOf): \ if (!IsOneofPresent(base, field_metadata.has_offset, field_metadata.tag)) \ continue; \ OneOfFieldHelper::Serialize(ptr, field_metadata, output); \ break void SerializeInternal(const uint8_t* base, const FieldMetadata* field_metadata_table, int32_t num_fields, io::CodedOutputStream* output) { SpecialSerializer func = nullptr; for (int i = 0; i < num_fields; i++) { const FieldMetadata& field_metadata = field_metadata_table[i]; const uint8_t* ptr = base + field_metadata.offset; switch (field_metadata.type) { SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64); SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType); // Special cases case FieldMetadata::kSpecial: func = reinterpret_cast( const_cast(field_metadata.ptr)); func(base, field_metadata.offset, field_metadata.tag, field_metadata.has_offset, output); break; default: // __builtin_unreachable() SerializeNotImplemented(field_metadata.type); } } } uint8_t* SerializeInternalToArray(const uint8_t* base, const FieldMetadata* field_metadata_table, int32_t num_fields, bool is_deterministic, uint8_t* buffer) { ArrayOutput array_output = {buffer, is_deterministic}; ArrayOutput* output = &array_output; SpecialSerializer func = nullptr; for (int i = 0; i < num_fields; i++) { const FieldMetadata& field_metadata = field_metadata_table[i]; const uint8_t* ptr = base + field_metadata.offset; switch (field_metadata.type) { SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_DOUBLE); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FLOAT); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_INT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_FIXED32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BOOL); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_STRING); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_GROUP); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_MESSAGE); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_BYTES); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_UINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_ENUM); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SFIXED64); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT32); SERIALIZERS_FOR_TYPE(WireFormatLite::TYPE_SINT64); SERIALIZERS_FOR_TYPE(FieldMetadata::kInlinedType); // Special cases case FieldMetadata::kSpecial: { io::ArrayOutputStream array_stream(array_output.ptr, INT_MAX); io::CodedOutputStream output_stream(&array_stream); output_stream.SetSerializationDeterministic(is_deterministic); func = reinterpret_cast( const_cast(field_metadata.ptr)); func(base, field_metadata.offset, field_metadata.tag, field_metadata.has_offset, &output_stream); array_output.ptr += output_stream.ByteCount(); } break; default: // __builtin_unreachable() SerializeNotImplemented(field_metadata.type); } } return array_output.ptr; } #undef SERIALIZERS_FOR_TYPE void ExtensionSerializer(const MessageLite* extendee, const uint8_t* ptr, uint32_t offset, uint32_t tag, uint32_t has_offset, io::CodedOutputStream* output) { reinterpret_cast(ptr + offset) ->SerializeWithCachedSizes(extendee, tag, has_offset, output); } void UnknownFieldSerializerLite(const uint8_t* ptr, uint32_t offset, uint32_t /*tag*/, uint32_t /*has_offset*/, io::CodedOutputStream* output) { output->WriteString( reinterpret_cast(ptr + offset) ->unknown_fields(&internal::GetEmptyString)); } MessageLite* DuplicateIfNonNullInternal(MessageLite* message) { if (message) { MessageLite* ret = message->New(); ret->CheckTypeAndMergeFrom(*message); return ret; } else { return nullptr; } } void GenericSwap(MessageLite* m1, MessageLite* m2) { std::unique_ptr tmp(m1->New()); tmp->CheckTypeAndMergeFrom(*m1); m1->Clear(); m1->CheckTypeAndMergeFrom(*m2); m2->Clear(); m2->CheckTypeAndMergeFrom(*tmp); } // Returns a message owned by this Arena. This may require Own()ing or // duplicating the message. MessageLite* GetOwnedMessageInternal(Arena* message_arena, MessageLite* submessage, Arena* submessage_arena) { GOOGLE_DCHECK(Arena::InternalHelper::GetOwningArena(submessage) == submessage_arena); GOOGLE_DCHECK(message_arena != submessage_arena); GOOGLE_DCHECK_EQ(submessage_arena, nullptr); if (message_arena != nullptr && submessage_arena == nullptr) { message_arena->Own(submessage); return submessage; } else { MessageLite* ret = submessage->New(message_arena); ret->CheckTypeAndMergeFrom(*submessage); return ret; } } } // namespace internal } // namespace protobuf } // namespace google #include