generated_message_table_driven.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. // Protocol Buffers - Google's data interchange format
  2. // Copyright 2008 Google Inc. All rights reserved.
  3. // https://developers.google.com/protocol-buffers/
  4. //
  5. // Redistribution and use in source and binary forms, with or without
  6. // modification, are permitted provided that the following conditions are
  7. // met:
  8. //
  9. // * Redistributions of source code must retain the above copyright
  10. // notice, this list of conditions and the following disclaimer.
  11. // * Redistributions in binary form must reproduce the above
  12. // copyright notice, this list of conditions and the following disclaimer
  13. // in the documentation and/or other materials provided with the
  14. // distribution.
  15. // * Neither the name of Google Inc. nor the names of its
  16. // contributors may be used to endorse or promote products derived from
  17. // this software without specific prior written permission.
  18. //
  19. // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  20. // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  21. // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  22. // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  23. // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  25. // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  26. // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  27. // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  28. // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  29. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  30. #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
  31. #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__
  32. #include <google/protobuf/map.h>
  33. #include <google/protobuf/map_entry_lite.h>
  34. #include <google/protobuf/map_field_lite.h>
  35. #include <google/protobuf/message_lite.h>
  36. #include <google/protobuf/wire_format_lite.h>
  37. // We require C++11 and Clang to use constexpr for variables, as GCC 4.8
  38. // requires constexpr to be consistent between declarations of variables
  39. // unnecessarily (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58541).
  40. // VS 2017 Update 3 also supports this usage of constexpr.
  41. #if defined(__clang__) || (defined(_MSC_VER) && _MSC_VER >= 1911)
  42. #define PROTOBUF_CONSTEXPR_VAR constexpr
  43. #else // !__clang__
  44. #define PROTOBUF_CONSTEXPR_VAR
  45. #endif // !_clang
  46. #ifdef SWIG
  47. #error "You cannot SWIG proto headers"
  48. #endif
  49. #include <google/protobuf/port_def.inc>
  50. namespace google {
  51. namespace protobuf {
  52. namespace internal {
  53. // Processing-type masks.
  54. static constexpr const unsigned char kOneofMask = 0x40;
  55. static constexpr const unsigned char kRepeatedMask = 0x20;
  56. // Mask for the raw type: either a WireFormatLite::FieldType or one of the
  57. // ProcessingTypes below, without the oneof or repeated flag.
  58. static constexpr const unsigned char kTypeMask = 0x1f;
  59. // Wire type masks.
  60. static constexpr const unsigned char kNotPackedMask = 0x10;
  61. static constexpr const unsigned char kInvalidMask = 0x20;
  62. enum ProcessingTypes {
  63. TYPE_STRING_CORD = 19,
  64. TYPE_STRING_STRING_PIECE = 20,
  65. TYPE_BYTES_CORD = 21,
  66. TYPE_BYTES_STRING_PIECE = 22,
  67. TYPE_STRING_INLINED = 23,
  68. TYPE_BYTES_INLINED = 24,
  69. TYPE_MAP = 25,
  70. };
  71. static_assert(TYPE_MAP < kRepeatedMask, "Invalid enum");
  72. struct PROTOBUF_EXPORT FieldMetadata {
  73. uint32_t offset; // offset of this field in the struct
  74. uint32_t tag; // field * 8 + wire_type
  75. // byte offset * 8 + bit_offset;
  76. // if the high bit is set then this is the byte offset of the oneof_case
  77. // for this field.
  78. uint32_t has_offset;
  79. uint32_t type; // the type of this field.
  80. const void* ptr; // auxiliary data
  81. // From the serializer point of view each fundamental type can occur in
  82. // 4 different ways. For simplicity we treat all combinations as a cartesion
  83. // product although not all combinations are allowed.
  84. enum FieldTypeClass {
  85. kPresence,
  86. kNoPresence,
  87. kRepeated,
  88. kPacked,
  89. kOneOf,
  90. kNumTypeClasses // must be last enum
  91. };
  92. // C++ protobuf has 20 fundamental types, were we added Cord and StringPiece
  93. // and also distinguish the same types if they have different wire format.
  94. enum {
  95. kCordType = 19,
  96. kStringPieceType = 20,
  97. kInlinedType = 21,
  98. kNumTypes = 21,
  99. kSpecial = kNumTypes * kNumTypeClasses,
  100. };
  101. static int CalculateType(int fundamental_type, FieldTypeClass type_class);
  102. };
  103. // TODO(ckennelly): Add a static assertion to ensure that these masks do not
  104. // conflict with wiretypes.
  105. // ParseTableField is kept small to help simplify instructions for computing
  106. // offsets, as we will always need this information to parse a field.
  107. // Additional data, needed for some types, is stored in
  108. // AuxiliaryParseTableField.
  109. struct ParseTableField {
  110. uint32_t offset;
  111. // The presence_index ordinarily represents a has_bit index, but for fields
  112. // inside a oneof it represents the index in _oneof_case_.
  113. uint32_t presence_index;
  114. unsigned char normal_wiretype;
  115. unsigned char packed_wiretype;
  116. // processing_type is given by:
  117. // (FieldDescriptor->type() << 1) | FieldDescriptor->is_packed()
  118. unsigned char processing_type;
  119. unsigned char tag_size;
  120. };
  121. struct ParseTable;
  122. union AuxiliaryParseTableField {
  123. typedef bool (*EnumValidator)(int);
  124. // Enums
  125. struct enum_aux {
  126. EnumValidator validator;
  127. };
  128. enum_aux enums;
  129. // Group, messages
  130. struct message_aux {
  131. // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
  132. // the tables from being constructed as a constexpr. We use void to avoid
  133. // the cast.
  134. const void* default_message_void;
  135. const MessageLite* default_message() const {
  136. return static_cast<const MessageLite*>(default_message_void);
  137. }
  138. };
  139. message_aux messages;
  140. // Strings
  141. struct string_aux {
  142. const void* default_ptr;
  143. const char* field_name;
  144. };
  145. string_aux strings;
  146. struct map_aux {
  147. bool (*parse_map)(io::CodedInputStream*, void*);
  148. };
  149. map_aux maps;
  150. AuxiliaryParseTableField() = default;
  151. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::enum_aux e)
  152. : enums(e) {}
  153. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::message_aux m)
  154. : messages(m) {}
  155. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::string_aux s)
  156. : strings(s) {}
  157. constexpr AuxiliaryParseTableField(AuxiliaryParseTableField::map_aux m)
  158. : maps(m) {}
  159. };
  160. struct ParseTable {
  161. const ParseTableField* fields;
  162. const AuxiliaryParseTableField* aux;
  163. int max_field_number;
  164. // TODO(ckennelly): Do something with this padding.
  165. // TODO(ckennelly): Vet these for sign extension.
  166. int64_t has_bits_offset;
  167. int64_t oneof_case_offset;
  168. int64_t extension_offset;
  169. int64_t arena_offset;
  170. // ExplicitlyInitialized<T> -> T requires a reinterpret_cast, which prevents
  171. // the tables from being constructed as a constexpr. We use void to avoid
  172. // the cast.
  173. const void* default_instance_void;
  174. const MessageLite* default_instance() const {
  175. return static_cast<const MessageLite*>(default_instance_void);
  176. }
  177. bool unknown_field_set;
  178. };
  179. static_assert(sizeof(ParseTableField) <= 16, "ParseTableField is too large");
  180. // The tables must be composed of POD components to ensure link-time
  181. // initialization.
  182. static_assert(std::is_standard_layout<ParseTableField>::value, "");
  183. static_assert(std::is_trivial<ParseTableField>::value, "");
  184. static_assert(std::is_standard_layout<AuxiliaryParseTableField>::value, "");
  185. static_assert(std::is_trivial<AuxiliaryParseTableField>::value, "");
  186. static_assert(
  187. std::is_standard_layout<AuxiliaryParseTableField::enum_aux>::value, "");
  188. static_assert(std::is_trivial<AuxiliaryParseTableField::enum_aux>::value, "");
  189. static_assert(
  190. std::is_standard_layout<AuxiliaryParseTableField::message_aux>::value, "");
  191. static_assert(std::is_trivial<AuxiliaryParseTableField::message_aux>::value,
  192. "");
  193. static_assert(
  194. std::is_standard_layout<AuxiliaryParseTableField::string_aux>::value, "");
  195. static_assert(std::is_trivial<AuxiliaryParseTableField::string_aux>::value, "");
  196. static_assert(std::is_standard_layout<ParseTable>::value, "");
  197. static_assert(std::is_trivial<ParseTable>::value, "");
  198. // TODO(ckennelly): Consolidate these implementations into a single one, using
  199. // dynamic dispatch to the appropriate unknown field handler.
  200. bool MergePartialFromCodedStream(MessageLite* msg, const ParseTable& table,
  201. io::CodedInputStream* input);
  202. bool MergePartialFromCodedStreamLite(MessageLite* msg, const ParseTable& table,
  203. io::CodedInputStream* input);
  204. template <typename Entry>
  205. bool ParseMap(io::CodedInputStream* input, void* map_field) {
  206. typedef typename MapEntryToMapField<Entry>::MapFieldType MapFieldType;
  207. typedef Map<typename Entry::EntryKeyType, typename Entry::EntryValueType>
  208. MapType;
  209. typedef typename Entry::template Parser<MapFieldType, MapType> ParserType;
  210. ParserType parser(static_cast<MapFieldType*>(map_field));
  211. return WireFormatLite::ReadMessageNoVirtual(input, &parser);
  212. }
  213. struct SerializationTable {
  214. int num_fields;
  215. const FieldMetadata* field_table;
  216. };
  217. PROTOBUF_EXPORT void SerializeInternal(const uint8_t* base,
  218. const FieldMetadata* table,
  219. int32_t num_fields,
  220. io::CodedOutputStream* output);
  221. inline void TableSerialize(const MessageLite& msg,
  222. const SerializationTable* table,
  223. io::CodedOutputStream* output) {
  224. const FieldMetadata* field_table = table->field_table;
  225. int num_fields = table->num_fields - 1;
  226. const uint8_t* base = reinterpret_cast<const uint8_t*>(&msg);
  227. // TODO(gerbens) This skips the first test if we could use the fast
  228. // array serialization path, we should make this
  229. // int cached_size =
  230. // *reinterpret_cast<const int32_t*>(base + field_table->offset);
  231. // SerializeWithCachedSize(msg, field_table + 1, num_fields, cached_size, ...)
  232. // But we keep conformance with the old way for now.
  233. SerializeInternal(base, field_table + 1, num_fields, output);
  234. }
  235. PROTOBUF_EXPORT uint8_t* SerializeInternalToArray(const uint8_t* base,
  236. const FieldMetadata* table,
  237. int32_t num_fields, bool is_deterministic,
  238. uint8_t* buffer);
  239. inline uint8_t* TableSerializeToArray(const MessageLite& msg,
  240. const SerializationTable* table,
  241. bool is_deterministic, uint8_t* buffer) {
  242. const uint8_t* base = reinterpret_cast<const uint8_t*>(&msg);
  243. const FieldMetadata* field_table = table->field_table + 1;
  244. int num_fields = table->num_fields - 1;
  245. return SerializeInternalToArray(base, field_table, num_fields,
  246. is_deterministic, buffer);
  247. }
  248. template <typename T>
  249. struct CompareHelper {
  250. bool operator()(const T& a, const T& b) const { return a < b; }
  251. };
  252. template <>
  253. struct CompareHelper<ArenaStringPtr> {
  254. bool operator()(const ArenaStringPtr& a, const ArenaStringPtr& b) const {
  255. return a.Get() < b.Get();
  256. }
  257. };
  258. struct CompareMapKey {
  259. template <typename T>
  260. bool operator()(const MapEntryHelper<T>& a,
  261. const MapEntryHelper<T>& b) const {
  262. return Compare(a.key_, b.key_);
  263. }
  264. template <typename T>
  265. bool Compare(const T& a, const T& b) const {
  266. return CompareHelper<T>()(a, b);
  267. }
  268. };
  269. template <typename MapFieldType, const SerializationTable* table>
  270. void MapFieldSerializer(const uint8_t* base, uint32_t offset, uint32_t tag,
  271. uint32_t has_offset, io::CodedOutputStream* output) {
  272. typedef MapEntryHelper<typename MapFieldType::EntryTypeTrait> Entry;
  273. typedef typename MapFieldType::MapType::const_iterator Iter;
  274. const MapFieldType& map_field =
  275. *reinterpret_cast<const MapFieldType*>(base + offset);
  276. const SerializationTable* t =
  277. table +
  278. has_offset; // has_offset is overloaded for maps to mean table offset
  279. if (!output->IsSerializationDeterministic()) {
  280. for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
  281. ++it) {
  282. Entry map_entry(*it);
  283. output->WriteVarint32(tag);
  284. output->WriteVarint32(map_entry._cached_size_);
  285. SerializeInternal(reinterpret_cast<const uint8_t*>(&map_entry),
  286. t->field_table, t->num_fields, output);
  287. }
  288. } else {
  289. std::vector<Entry> v;
  290. for (Iter it = map_field.GetMap().begin(); it != map_field.GetMap().end();
  291. ++it) {
  292. v.push_back(Entry(*it));
  293. }
  294. std::sort(v.begin(), v.end(), CompareMapKey());
  295. for (int i = 0; i < v.size(); i++) {
  296. output->WriteVarint32(tag);
  297. output->WriteVarint32(v[i]._cached_size_);
  298. SerializeInternal(reinterpret_cast<const uint8_t*>(&v[i]), t->field_table,
  299. t->num_fields, output);
  300. }
  301. }
  302. }
  303. } // namespace internal
  304. } // namespace protobuf
  305. } // namespace google
  306. #include <google/protobuf/port_undef.inc>
  307. #endif // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TABLE_DRIVEN_H__