• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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