1 // Protocol Buffers - Google's data interchange format 2 // Copyright 2008 Google Inc. All rights reserved. 3 // 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file or at 6 // https://developers.google.com/open-source/licenses/bsd 7 8 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__ 9 #define GOOGLE_PROTOBUF_MAP_ENTRY_H__ 10 11 #include <cstddef> 12 #include <cstdint> 13 #include <string> 14 #include <type_traits> 15 16 #include "google/protobuf/generated_message_reflection.h" 17 #include "google/protobuf/has_bits.h" 18 #include "google/protobuf/map_type_handler.h" 19 #include "google/protobuf/message.h" 20 #include "google/protobuf/message_lite.h" 21 #include "google/protobuf/parse_context.h" 22 #include "google/protobuf/unknown_field_set.h" 23 #include "google/protobuf/wire_format_lite.h" 24 25 // Must be included last. 26 #include "google/protobuf/port_def.inc" 27 28 #ifdef SWIG 29 #error "You cannot SWIG proto headers" 30 #endif 31 32 namespace google { 33 namespace protobuf { 34 35 class Arena; 36 37 namespace internal { 38 39 // MapEntry is the returned google::protobuf::Message when calling AddMessage of 40 // google::protobuf::Reflection. In order to let it work with generated message 41 // reflection, its in-memory type is the same as generated message with the same 42 // fields. However, in order to decide the in-memory type of key/value, we need 43 // to know both their cpp type in generated api and proto type. In 44 // implementation, all in-memory types have related wire format functions to 45 // support except ArenaStringPtr. Therefore, we need to define another type with 46 // supporting wire format functions. Since this type is only used as return type 47 // of MapEntry accessors, it's named MapEntry accessor type. 48 // 49 // cpp type: the type visible to users in public API. 50 // proto type: WireFormatLite::FieldType of the field. 51 // in-memory type: type of the data member used to stored this field. 52 // MapEntry accessor type: type used in MapEntry getters/mutators to access the 53 // field. 54 // 55 // cpp type | proto type | in-memory type | MapEntry accessor type 56 // int32_t TYPE_INT32 int32_t int32_t 57 // int32_t TYPE_FIXED32 int32_t int32_t 58 // string TYPE_STRING ArenaStringPtr string 59 // FooEnum TYPE_ENUM int int 60 // FooMessage TYPE_MESSAGE FooMessage* FooMessage 61 // 62 // The in-memory types of primitive types can be inferred from its proto type, 63 // while we need to explicitly specify the cpp type if proto type is 64 // TYPE_MESSAGE to infer the in-memory type. 65 template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, 66 WireFormatLite::FieldType kValueFieldType> 67 class MapEntry : public Message { 68 // Provide utilities to parse/serialize key/value. Provide utilities to 69 // manipulate internal stored type. 70 using KeyTypeHandler = MapTypeHandler<kKeyFieldType, Key>; 71 using ValueTypeHandler = MapTypeHandler<kValueFieldType, Value>; 72 73 // Define internal memory layout. Strings and messages are stored as 74 // pointers, while other types are stored as values. 75 using KeyOnMemory = typename KeyTypeHandler::TypeOnMemory; 76 using ValueOnMemory = typename ValueTypeHandler::TypeOnMemory; 77 78 public: 79 #if !defined(PROTOBUF_CUSTOM_VTABLE) MapEntry()80 constexpr MapEntry() {} 81 #endif // PROTOBUF_CUSTOM_VTABLE 82 using Message::Message; 83 84 MapEntry(const MapEntry&) = delete; 85 MapEntry& operator=(const MapEntry&) = delete; 86 ~MapEntry()87 ~MapEntry() PROTOBUF_OVERRIDE { 88 // Make sure that `Value` is never a derived message type. 89 // We don't want to instantiate the template with every unique derived type. 90 // The assertion is in the destructor because we need `Value` to be 91 // complete to test it. 92 static_assert(!std::is_base_of<Message, Value>::value || 93 std::is_same<Message, Value>::value, 94 ""); 95 96 if (GetArena() != nullptr) return; 97 SharedDtor(*this); 98 } 99 100 using InternalArenaConstructable_ = void; 101 using DestructorSkippable_ = void; 102 103 struct _Internal; 104 105 protected: 106 friend class google::protobuf::Arena; 107 SharedDtor(MessageLite & msg)108 static void SharedDtor(MessageLite& msg) { 109 auto& this_ = static_cast<MapEntry&>(msg); 110 this_._internal_metadata_.template Delete<UnknownFieldSet>(); 111 KeyTypeHandler::DeleteNoArena(this_._impl_.key_); 112 ValueTypeHandler::DeleteNoArena(this_._impl_.value_); 113 } 114 115 // Field naming follows the convention of generated messages to make code 116 // sharing easier. 117 struct { 118 HasBits<1> _has_bits_{}; 119 CachedSize _cached_size_{}; 120 121 KeyOnMemory key_{KeyTypeHandler::Constinit()}; 122 ValueOnMemory value_{ValueTypeHandler::Constinit()}; 123 } _impl_; 124 }; 125 126 template <typename Key, typename Value, WireFormatLite::FieldType kKeyFieldType, 127 WireFormatLite::FieldType kValueFieldType> 128 struct MapEntry<Key, Value, kKeyFieldType, kValueFieldType>::_Internal { 129 static constexpr ::int32_t kHasBitsOffset = 130 8 * PROTOBUF_FIELD_OFFSET(MapEntry, _impl_._has_bits_); 131 }; 132 133 } // namespace internal 134 } // namespace protobuf 135 } // namespace google 136 137 #include "google/protobuf/port_undef.inc" 138 139 #endif // GOOGLE_PROTOBUF_MAP_ENTRY_H__ 140