• 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_FIELD_H__
9 #define GOOGLE_PROTOBUF_MAP_FIELD_H__
10 
11 #include <atomic>
12 #include <cstddef>
13 #include <cstdint>
14 #include <functional>
15 #include <string>
16 #include <type_traits>
17 #include <utility>
18 
19 #include "absl/log/absl_check.h"
20 #include "absl/log/absl_log.h"
21 #include "absl/strings/string_view.h"
22 #include "absl/synchronization/mutex.h"
23 #include "google/protobuf/arena.h"
24 #include "google/protobuf/descriptor.h"
25 #include "google/protobuf/explicitly_constructed.h"
26 #include "google/protobuf/generated_message_reflection.h"
27 #include "google/protobuf/generated_message_util.h"
28 #include "google/protobuf/internal_visibility.h"
29 #include "google/protobuf/map.h"
30 #include "google/protobuf/map_field_lite.h"
31 #include "google/protobuf/map_type_handler.h"
32 #include "google/protobuf/message.h"
33 #include "google/protobuf/message_lite.h"
34 #include "google/protobuf/port.h"
35 #include "google/protobuf/repeated_field.h"
36 #include "google/protobuf/unknown_field_set.h"
37 
38 
39 // Must be included last.
40 #include "google/protobuf/port_def.inc"
41 
42 #ifdef SWIG
43 #error "You cannot SWIG proto headers"
44 #endif
45 
46 namespace google {
47 namespace protobuf {
48 class DynamicMessage;
49 class MapIterator;
50 
51 // Microsoft compiler complains about non-virtual destructor,
52 // even when the destructor is private.
53 #ifdef _MSC_VER
54 #pragma warning(push)
55 #pragma warning(disable : 4265)
56 #endif  // _MSC_VER
57 
58 #define TYPE_CHECK(EXPECTEDTYPE, METHOD)                                  \
59   if (type() != EXPECTEDTYPE) {                                           \
60     ABSL_LOG(FATAL) << "Protocol Buffer map usage error:\n"               \
61                     << METHOD << " type does not match\n"                 \
62                     << "  Expected : "                                    \
63                     << FieldDescriptor::CppTypeName(EXPECTEDTYPE) << "\n" \
64                     << "  Actual   : "                                    \
65                     << FieldDescriptor::CppTypeName(type());              \
66   }
67 
68 // MapKey is an union type for representing any possible
69 // map key.
70 class PROTOBUF_EXPORT MapKey {
71  public:
MapKey()72   MapKey() : type_() {}
MapKey(const MapKey & other)73   MapKey(const MapKey& other) : type_() { CopyFrom(other); }
74 
75   MapKey& operator=(const MapKey& other) {
76     CopyFrom(other);
77     return *this;
78   }
79 
~MapKey()80   ~MapKey() {
81     if (type_ == FieldDescriptor::CPPTYPE_STRING) {
82       val_.string_value.Destruct();
83     }
84   }
85 
type()86   FieldDescriptor::CppType type() const {
87     if (type_ == FieldDescriptor::CppType()) {
88       ABSL_LOG(FATAL) << "Protocol Buffer map usage error:\n"
89                       << "MapKey::type MapKey is not initialized. "
90                       << "Call set methods to initialize MapKey.";
91     }
92     return type_;
93   }
94 
SetInt64Value(int64_t value)95   void SetInt64Value(int64_t value) {
96     SetType(FieldDescriptor::CPPTYPE_INT64);
97     val_.int64_value = value;
98   }
SetUInt64Value(uint64_t value)99   void SetUInt64Value(uint64_t value) {
100     SetType(FieldDescriptor::CPPTYPE_UINT64);
101     val_.uint64_value = value;
102   }
SetInt32Value(int32_t value)103   void SetInt32Value(int32_t value) {
104     SetType(FieldDescriptor::CPPTYPE_INT32);
105     val_.int32_value = value;
106   }
SetUInt32Value(uint32_t value)107   void SetUInt32Value(uint32_t value) {
108     SetType(FieldDescriptor::CPPTYPE_UINT32);
109     val_.uint32_value = value;
110   }
SetBoolValue(bool value)111   void SetBoolValue(bool value) {
112     SetType(FieldDescriptor::CPPTYPE_BOOL);
113     val_.bool_value = value;
114   }
SetStringValue(absl::string_view val)115   void SetStringValue(absl::string_view val) {
116     SetType(FieldDescriptor::CPPTYPE_STRING);
117     val_.string_value.get_mutable()->assign(val.data(), val.size());
118   }
119 
GetInt64Value()120   int64_t GetInt64Value() const {
121     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapKey::GetInt64Value");
122     return val_.int64_value;
123   }
GetUInt64Value()124   uint64_t GetUInt64Value() const {
125     TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapKey::GetUInt64Value");
126     return val_.uint64_value;
127   }
GetInt32Value()128   int32_t GetInt32Value() const {
129     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapKey::GetInt32Value");
130     return val_.int32_value;
131   }
GetUInt32Value()132   uint32_t GetUInt32Value() const {
133     TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapKey::GetUInt32Value");
134     return val_.uint32_value;
135   }
GetBoolValue()136   bool GetBoolValue() const {
137     TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapKey::GetBoolValue");
138     return val_.bool_value;
139   }
GetStringValue()140   absl::string_view GetStringValue() const {
141     TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapKey::GetStringValue");
142     return val_.string_value.get();
143   }
144 
145   bool operator<(const MapKey& other) const {
146     if (type_ != other.type_) {
147       // We could define a total order that handles this case, but
148       // there currently no need.  So, for now, fail.
149       ABSL_LOG(FATAL) << "Unsupported: type mismatch";
150     }
151     switch (type()) {
152       case FieldDescriptor::CPPTYPE_DOUBLE:
153       case FieldDescriptor::CPPTYPE_FLOAT:
154       case FieldDescriptor::CPPTYPE_ENUM:
155       case FieldDescriptor::CPPTYPE_MESSAGE:
156         ABSL_LOG(FATAL) << "Unsupported";
157         return false;
158       case FieldDescriptor::CPPTYPE_STRING:
159         return val_.string_value.get() < other.val_.string_value.get();
160       case FieldDescriptor::CPPTYPE_INT64:
161         return val_.int64_value < other.val_.int64_value;
162       case FieldDescriptor::CPPTYPE_INT32:
163         return val_.int32_value < other.val_.int32_value;
164       case FieldDescriptor::CPPTYPE_UINT64:
165         return val_.uint64_value < other.val_.uint64_value;
166       case FieldDescriptor::CPPTYPE_UINT32:
167         return val_.uint32_value < other.val_.uint32_value;
168       case FieldDescriptor::CPPTYPE_BOOL:
169         return val_.bool_value < other.val_.bool_value;
170     }
171     return false;
172   }
173 
174   bool operator==(const MapKey& other) const {
175     if (type_ != other.type_) {
176       // To be consistent with operator<, we don't allow this either.
177       ABSL_LOG(FATAL) << "Unsupported: type mismatch";
178     }
179     switch (type()) {
180       case FieldDescriptor::CPPTYPE_DOUBLE:
181       case FieldDescriptor::CPPTYPE_FLOAT:
182       case FieldDescriptor::CPPTYPE_ENUM:
183       case FieldDescriptor::CPPTYPE_MESSAGE:
184         ABSL_LOG(FATAL) << "Unsupported";
185         break;
186       case FieldDescriptor::CPPTYPE_STRING:
187         return val_.string_value.get() == other.val_.string_value.get();
188       case FieldDescriptor::CPPTYPE_INT64:
189         return val_.int64_value == other.val_.int64_value;
190       case FieldDescriptor::CPPTYPE_INT32:
191         return val_.int32_value == other.val_.int32_value;
192       case FieldDescriptor::CPPTYPE_UINT64:
193         return val_.uint64_value == other.val_.uint64_value;
194       case FieldDescriptor::CPPTYPE_UINT32:
195         return val_.uint32_value == other.val_.uint32_value;
196       case FieldDescriptor::CPPTYPE_BOOL:
197         return val_.bool_value == other.val_.bool_value;
198     }
199     ABSL_LOG(FATAL) << "Can't get here.";
200     return false;
201   }
202 
CopyFrom(const MapKey & other)203   void CopyFrom(const MapKey& other) {
204     SetType(other.type());
205     switch (type_) {
206       case FieldDescriptor::CPPTYPE_DOUBLE:
207       case FieldDescriptor::CPPTYPE_FLOAT:
208       case FieldDescriptor::CPPTYPE_ENUM:
209       case FieldDescriptor::CPPTYPE_MESSAGE:
210         ABSL_LOG(FATAL) << "Unsupported";
211         break;
212       case FieldDescriptor::CPPTYPE_STRING:
213         *val_.string_value.get_mutable() = other.val_.string_value.get();
214         break;
215       case FieldDescriptor::CPPTYPE_INT64:
216         val_.int64_value = other.val_.int64_value;
217         break;
218       case FieldDescriptor::CPPTYPE_INT32:
219         val_.int32_value = other.val_.int32_value;
220         break;
221       case FieldDescriptor::CPPTYPE_UINT64:
222         val_.uint64_value = other.val_.uint64_value;
223         break;
224       case FieldDescriptor::CPPTYPE_UINT32:
225         val_.uint32_value = other.val_.uint32_value;
226         break;
227       case FieldDescriptor::CPPTYPE_BOOL:
228         val_.bool_value = other.val_.bool_value;
229         break;
230     }
231   }
232 
233  private:
234   template <typename K, typename V>
235   friend class internal::TypeDefinedMapFieldBase;
236   friend class internal::MapFieldBase;
237   friend class MapIterator;
238   friend class internal::DynamicMapField;
239 
240   union KeyValue {
KeyValue()241     KeyValue() {}
242     internal::ExplicitlyConstructed<std::string> string_value;
243     int64_t int64_value;
244     int32_t int32_value;
245     uint64_t uint64_value;
246     uint32_t uint32_value;
247     bool bool_value;
248   } val_;
249 
SetType(FieldDescriptor::CppType type)250   void SetType(FieldDescriptor::CppType type) {
251     if (type_ == type) return;
252     if (type_ == FieldDescriptor::CPPTYPE_STRING) {
253       val_.string_value.Destruct();
254     }
255     type_ = type;
256     if (type_ == FieldDescriptor::CPPTYPE_STRING) {
257       val_.string_value.DefaultConstruct();
258     }
259   }
260 
261   // type_ is 0 or a valid FieldDescriptor::CppType.
262   // Use "CppType()" to indicate zero.
263   FieldDescriptor::CppType type_;
264 };
265 
266 namespace internal {
267 
268 template <>
269 struct is_internal_map_key_type<MapKey> : std::true_type {};
270 
271 template <>
272 struct RealKeyToVariantKey<MapKey> {
273   VariantKey operator()(const MapKey& value) const;
274 };
275 
276 template <>
277 struct RealKeyToVariantKeyAlternative<MapKey> {
278   VariantKey operator()(const MapKey& value) const {
279     return RealKeyToVariantKey<MapKey>{}(value);
280   }
281 };
282 
283 }  // namespace internal
284 
285 namespace internal {
286 
287 class ContendedMapCleanTest;
288 class GeneratedMessageReflection;
289 class MapFieldAccessor;
290 
291 template <typename MessageT>
292 struct MapDynamicFieldInfo;
293 struct MapFieldTestPeer;
294 
295 // This class provides access to map field using reflection, which is the same
296 // as those provided for RepeatedPtrField<Message>. It is used for internal
297 // reflection implementation only. Users should never use this directly.
298 class PROTOBUF_EXPORT MapFieldBase : public MapFieldBaseForParse {
299  public:
300   explicit constexpr MapFieldBase(const VTable* vtable)
301       : MapFieldBaseForParse(vtable) {}
302   explicit MapFieldBase(const VTable* vtable, Arena* arena)
303       : MapFieldBaseForParse(vtable), payload_{ToTaggedPtr(arena)} {}
304   MapFieldBase(const MapFieldBase&) = delete;
305   MapFieldBase& operator=(const MapFieldBase&) = delete;
306 
307  protected:
308   // "protected" stops users from deleting a `MapFieldBase *`
309   ~MapFieldBase();
310 
311   struct VTable : MapFieldBaseForParse::VTable {
312     bool (*lookup_map_value)(const MapFieldBase& map, const MapKey& map_key,
313                              MapValueConstRef* val);
314     bool (*delete_map_value)(MapFieldBase& map, const MapKey& map_key);
315     void (*set_map_iterator_value)(MapIterator* map_iter);
316     bool (*insert_or_lookup_no_sync)(MapFieldBase& map, const MapKey& map_key,
317                                      MapValueRef* val);
318 
319     void (*clear_map_no_sync)(MapFieldBase& map);
320     void (*merge_from)(MapFieldBase& map, const MapFieldBase& other);
321     void (*swap)(MapFieldBase& lhs, MapFieldBase& rhs);
322     void (*unsafe_shallow_swap)(MapFieldBase& lhs, MapFieldBase& rhs);
323     size_t (*space_used_excluding_self_nolock)(const MapFieldBase& map);
324 
325     const Message* (*get_prototype)(const MapFieldBase& map);
326   };
327   template <typename T>
328   static constexpr VTable MakeVTable() {
329     VTable out{};
330     out.get_map = &T::GetMapImpl;
331     out.lookup_map_value = &T::LookupMapValueImpl;
332     out.delete_map_value = &T::DeleteMapValueImpl;
333     out.set_map_iterator_value = &T::SetMapIteratorValueImpl;
334     out.insert_or_lookup_no_sync = &T::InsertOrLookupMapValueNoSyncImpl;
335     out.clear_map_no_sync = &T::ClearMapNoSyncImpl;
336     out.merge_from = &T::MergeFromImpl;
337     out.swap = &T::SwapImpl;
338     out.unsafe_shallow_swap = &T::UnsafeShallowSwapImpl;
339     out.space_used_excluding_self_nolock = &T::SpaceUsedExcludingSelfNoLockImpl;
340     out.get_prototype = &T::GetPrototypeImpl;
341     return out;
342   }
343 
344  public:
345   // Returns reference to internal repeated field. Data written using
346   // Map's api prior to calling this function is guarantted to be
347   // included in repeated field.
348   const RepeatedPtrFieldBase& GetRepeatedField() const;
349 
350   // Like above. Returns mutable pointer to the internal repeated field.
351   RepeatedPtrFieldBase* MutableRepeatedField();
352 
353   const VTable* vtable() const { return static_cast<const VTable*>(vtable_); }
354 
355   bool ContainsMapKey(const MapKey& map_key) const {
356     return LookupMapValue(map_key, static_cast<MapValueConstRef*>(nullptr));
357   }
358   bool LookupMapValue(const MapKey& map_key, MapValueConstRef* val) const {
359     return vtable()->lookup_map_value(*this, map_key, val);
360   }
361   bool LookupMapValue(const MapKey&, MapValueRef*) const = delete;
362 
363   bool InsertOrLookupMapValue(const MapKey& map_key, MapValueRef* val);
364 
365   // Returns whether changes to the map are reflected in the repeated field.
366   bool IsRepeatedFieldValid() const;
367   // Insures operations after won't get executed before calling this.
368   bool IsMapValid() const;
369   bool DeleteMapValue(const MapKey& map_key) {
370     return vtable()->delete_map_value(*this, map_key);
371   }
372   void MergeFrom(const MapFieldBase& other) {
373     vtable()->merge_from(*this, other);
374   }
375   void Swap(MapFieldBase* other) { vtable()->swap(*this, *other); }
376   void UnsafeShallowSwap(MapFieldBase* other) {
377     vtable()->unsafe_shallow_swap(*this, *other);
378   }
379   // Sync Map with repeated field and returns the size of map.
380   int size() const;
381   void Clear();
382   void SetMapIteratorValue(MapIterator* map_iter) const {
383     return vtable()->set_map_iterator_value(map_iter);
384   }
385 
386   void MapBegin(MapIterator* map_iter) const;
387   void MapEnd(MapIterator* map_iter) const;
388   bool EqualIterator(const MapIterator& a, const MapIterator& b) const;
389 
390   // Returns the number of bytes used by the repeated field, excluding
391   // sizeof(*this)
392   size_t SpaceUsedExcludingSelfLong() const;
393 
394   int SpaceUsedExcludingSelf() const {
395     return internal::ToIntSize(SpaceUsedExcludingSelfLong());
396   }
397 
398   static constexpr size_t InternalGetArenaOffset(internal::InternalVisibility) {
399     return PROTOBUF_FIELD_OFFSET(MapFieldBase, payload_);
400   }
401 
402  protected:
403   // Gets the size of space used by map field.
404   size_t SpaceUsedExcludingSelfNoLock() const {
405     return vtable()->space_used_excluding_self_nolock(*this);
406   }
407 
408   const Message* GetPrototype() const { return vtable()->get_prototype(*this); }
409   void ClearMapNoSync() { return vtable()->clear_map_no_sync(*this); }
410 
411   // Synchronizes the content in Map to RepeatedPtrField if there is any change
412   // to Map after last synchronization.
413   const RepeatedPtrFieldBase& SyncRepeatedFieldWithMap(bool for_mutation) const;
414   void SyncRepeatedFieldWithMapNoLock();
415 
416   // Synchronizes the content in RepeatedPtrField to Map if there is any change
417   // to RepeatedPtrField after last synchronization.
418   void SyncMapWithRepeatedField() const;
419   void SyncMapWithRepeatedFieldNoLock();
420 
421   static void SwapImpl(MapFieldBase& lhs, MapFieldBase& rhs);
422   static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs);
423 
424   // Tells MapFieldBase that there is new change to Map.
425   void SetMapDirty();
426 
427   // Tells MapFieldBase that there is new change to RepeatedPtrField.
428   void SetRepeatedDirty();
429 
430   // Provides derived class the access to repeated field.
431   void* MutableRepeatedPtrField() const;
432 
433   bool InsertOrLookupMapValueNoSync(const MapKey& map_key, MapValueRef* val) {
434     return vtable()->insert_or_lookup_no_sync(*this, map_key, val);
435   }
436 
437   void InternalSwap(MapFieldBase* other);
438 
439   // Support thread sanitizer (tsan) by making const / mutable races
440   // more apparent.  If one thread calls MutableAccess() while another
441   // thread calls either ConstAccess() or MutableAccess(), on the same
442   // MapFieldBase-derived object, and there is no synchronization going
443   // on between them, tsan will alert.
444 #if defined(PROTOBUF_TSAN)
445   void ConstAccess() const { ABSL_CHECK_EQ(seq1_, seq2_); }
446   void MutableAccess() {
447     if (seq1_ & 1) {
448       seq2_ = ++seq1_;
449     } else {
450       seq1_ = ++seq2_;
451     }
452   }
453   unsigned int seq1_ = 0, seq2_ = 0;
454 #else
455   void ConstAccess() const {}
456   void MutableAccess() {}
457 #endif
458   enum State {
459     STATE_MODIFIED_MAP = 0,       // map has newly added data that has not been
460                                   // synchronized to repeated field
461     STATE_MODIFIED_REPEATED = 1,  // repeated field has newly added data that
462                                   // has not been synchronized to map
463     CLEAN = 2,                    // data in map and repeated field are same
464   };
465 
466   struct ReflectionPayload {
467     explicit ReflectionPayload(Arena* arena) : repeated_field(arena) {}
468     RepeatedPtrField<Message> repeated_field;
469 
470     absl::Mutex mutex;  // The thread to synchronize map and repeated
471                         // field needs to get lock first;
472     std::atomic<State> state{STATE_MODIFIED_MAP};
473   };
474 
475   Arena* arena() const {
476     auto p = payload_.load(std::memory_order_acquire);
477     if (IsPayload(p)) return ToPayload(p)->repeated_field.GetArena();
478     return ToArena(p);
479   }
480 
481   // Returns the reflection payload. Returns null if it does not exist yet.
482   ReflectionPayload* maybe_payload() const {
483     auto p = payload_.load(std::memory_order_acquire);
484     return IsPayload(p) ? ToPayload(p) : nullptr;
485   }
486   // Returns the reflection payload, and constructs one if does not exist yet.
487   ReflectionPayload& payload() const {
488     auto* p = maybe_payload();
489     return p != nullptr ? *p : PayloadSlow();
490   }
491   ReflectionPayload& PayloadSlow() const;
492 
493   State state() const {
494     auto* p = maybe_payload();
495     return p != nullptr ? p->state.load(std::memory_order_acquire)
496                         // The default
497                         : STATE_MODIFIED_MAP;
498   }
499 
500   static const UntypedMapBase& GetMapImpl(const MapFieldBaseForParse& map,
501                                           bool is_mutable);
502 
503  private:
504   friend class ContendedMapCleanTest;
505   friend class GeneratedMessageReflection;
506   friend class MapFieldAccessor;
507   friend class google::protobuf::Reflection;
508   friend class google::protobuf::DynamicMessage;
509 
510   // See assertion in TypeDefinedMapFieldBase::TypeDefinedMapFieldBase()
511   const UntypedMapBase& GetMapRaw() const {
512     return *reinterpret_cast<const UntypedMapBase*>(this + 1);
513   }
514   UntypedMapBase& GetMapRaw() {
515     return *reinterpret_cast<UntypedMapBase*>(this + 1);
516   }
517 
518   // Virtual helper methods for MapIterator. MapIterator doesn't have the
519   // type helper for key and value. Call these help methods to deal with
520   // different types. Real helper methods are implemented in
521   // TypeDefinedMapFieldBase.
522   friend class google::protobuf::MapIterator;
523 
524   // Copy the map<...>::iterator from other_iterator to
525   // this_iterator.
526   void CopyIterator(MapIterator* this_iter, const MapIterator& that_iter) const;
527 
528   // IncreaseIterator() is called by operator++() of MapIterator only.
529   // It implements the ++ operator of MapIterator.
530   void IncreaseIterator(MapIterator* map_iter) const;
531 
532   enum class TaggedPtr : uintptr_t {};
533   static constexpr uintptr_t kHasPayloadBit = 1;
534 
535   static ReflectionPayload* ToPayload(TaggedPtr p) {
536     ABSL_DCHECK(IsPayload(p));
537     auto* res = reinterpret_cast<ReflectionPayload*>(static_cast<uintptr_t>(p) -
538                                                      kHasPayloadBit);
539     PROTOBUF_ASSUME(res != nullptr);
540     return res;
541   }
542   static Arena* ToArena(TaggedPtr p) {
543     ABSL_DCHECK(!IsPayload(p));
544     return reinterpret_cast<Arena*>(p);
545   }
546   static TaggedPtr ToTaggedPtr(ReflectionPayload* p) {
547     return static_cast<TaggedPtr>(reinterpret_cast<uintptr_t>(p) +
548                                   kHasPayloadBit);
549   }
550   static TaggedPtr ToTaggedPtr(Arena* p) {
551     return static_cast<TaggedPtr>(reinterpret_cast<uintptr_t>(p));
552   }
553   static bool IsPayload(TaggedPtr p) {
554     return static_cast<uintptr_t>(p) & kHasPayloadBit;
555   }
556 
557   mutable std::atomic<TaggedPtr> payload_{};
558 };
559 
560 // This class provides common Map Reflection implementations for generated
561 // message and dynamic message.
562 template <typename Key, typename T>
563 class TypeDefinedMapFieldBase : public MapFieldBase {
564  public:
565   explicit constexpr TypeDefinedMapFieldBase(const VTable* vtable)
566       : MapFieldBase(vtable), map_() {
567     // This invariant is required by MapFieldBase to easily access the map
568     // member without paying for dynamic dispatch. It reduces code size.
569     static_assert(PROTOBUF_FIELD_OFFSET(TypeDefinedMapFieldBase, map_) ==
570                       sizeof(MapFieldBase),
571                   "");
572   }
573   TypeDefinedMapFieldBase(const TypeDefinedMapFieldBase&) = delete;
574   TypeDefinedMapFieldBase& operator=(const TypeDefinedMapFieldBase&) = delete;
575 
576   TypeDefinedMapFieldBase(const VTable* vtable, Arena* arena)
577       : MapFieldBase(vtable, arena), map_(arena) {}
578 
579  protected:
580   ~TypeDefinedMapFieldBase() { map_.~Map(); }
581 
582   // Not all overrides are marked `final` here because DynamicMapField overrides
583   // them. DynamicMapField does extra memory management for the elements and
584   // needs to override the functions that create or destroy elements.
585 
586  public:
587   const Map<Key, T>& GetMap() const {
588     SyncMapWithRepeatedField();
589     return map_;
590   }
591 
592   Map<Key, T>* MutableMap() {
593     SyncMapWithRepeatedField();
594     SetMapDirty();
595     return &map_;
596   }
597 
598   static void ClearMapNoSyncImpl(MapFieldBase& map) {
599     static_cast<TypeDefinedMapFieldBase&>(map).map_.clear();
600   }
601 
602   void InternalSwap(TypeDefinedMapFieldBase* other);
603 
604   static constexpr size_t InternalGetArenaOffsetAlt(
605       internal::InternalVisibility access) {
606     return PROTOBUF_FIELD_OFFSET(TypeDefinedMapFieldBase, map_) +
607            decltype(map_)::InternalGetArenaOffset(access);
608   }
609 
610  protected:
611   friend struct MapFieldTestPeer;
612 
613   using Iter = typename Map<Key, T>::const_iterator;
614 
615   static bool DeleteMapValueImpl(MapFieldBase& map, const MapKey& map_key);
616   static bool LookupMapValueImpl(const MapFieldBase& self,
617                                  const MapKey& map_key, MapValueConstRef* val);
618   static void SetMapIteratorValueImpl(MapIterator* map_iter);
619   static bool InsertOrLookupMapValueNoSyncImpl(MapFieldBase& map,
620                                                const MapKey& map_key,
621                                                MapValueRef* val);
622 
623   static void MergeFromImpl(MapFieldBase& base, const MapFieldBase& other);
624   static void SwapImpl(MapFieldBase& lhs, MapFieldBase& rhs);
625   static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs);
626 
627   static size_t SpaceUsedExcludingSelfNoLockImpl(const MapFieldBase& map);
628 
629   // map_ is inside an anonymous union so we can explicitly control its
630   // destruction
631   union {
632     Map<Key, T> map_;
633   };
634 };
635 
636 // This class provides access to map field using generated api. It is used for
637 // internal generated message implementation only. Users should never use this
638 // directly.
639 template <typename Derived, typename Key, typename T,
640           WireFormatLite::FieldType kKeyFieldType_,
641           WireFormatLite::FieldType kValueFieldType_>
642 class MapField final : public TypeDefinedMapFieldBase<Key, T> {
643   // Provide utilities to parse/serialize key/value.  Provide utilities to
644   // manipulate internal stored type.
645   typedef MapTypeHandler<kKeyFieldType_, Key> KeyTypeHandler;
646   typedef MapTypeHandler<kValueFieldType_, T> ValueTypeHandler;
647 
648  public:
649   typedef Map<Key, T> MapType;
650   static constexpr WireFormatLite::FieldType kKeyFieldType = kKeyFieldType_;
651   static constexpr WireFormatLite::FieldType kValueFieldType = kValueFieldType_;
652 
653   constexpr MapField() : MapField::TypeDefinedMapFieldBase(&kVTable) {}
654   MapField(const MapField&) = delete;
655   MapField& operator=(const MapField&) = delete;
656   ~MapField() = default;
657 
658   explicit MapField(Arena* arena)
659       : TypeDefinedMapFieldBase<Key, T>(&kVTable, arena) {}
660   MapField(ArenaInitialized, Arena* arena) : MapField(arena) {}
661   MapField(InternalVisibility, Arena* arena) : MapField(arena) {}
662   MapField(InternalVisibility, Arena* arena, const MapField& from)
663       : MapField(arena) {
664     this->MergeFromImpl(*this, from);
665   }
666 
667  private:
668   typedef void InternalArenaConstructable_;
669   typedef void DestructorSkippable_;
670 
671   static const Message* GetPrototypeImpl(const MapFieldBase& map);
672 
673   static const MapFieldBase::VTable kVTable;
674 
675   friend class google::protobuf::Arena;
676   friend class MapFieldBase;
677   friend class MapFieldStateTest;  // For testing, it needs raw access to impl_
678 };
679 
680 template <typename Derived, typename Key, typename T,
681           WireFormatLite::FieldType kKeyFieldType_,
682           WireFormatLite::FieldType kValueFieldType_>
683 PROTOBUF_CONSTINIT const MapFieldBase::VTable
684     MapField<Derived, Key, T, kKeyFieldType_, kValueFieldType_>::kVTable =
685         MapField::template MakeVTable<MapField>();
686 
687 template <typename Key, typename T>
688 bool AllAreInitialized(const TypeDefinedMapFieldBase<Key, T>& field) {
689   for (const auto& p : field.GetMap()) {
690     if (!p.second.IsInitialized()) return false;
691   }
692   return true;
693 }
694 
695 class PROTOBUF_EXPORT DynamicMapField final
696     : public TypeDefinedMapFieldBase<MapKey, MapValueRef> {
697  public:
698   explicit DynamicMapField(const Message* default_entry);
699   DynamicMapField(const Message* default_entry, Arena* arena);
700   DynamicMapField(const DynamicMapField&) = delete;
701   DynamicMapField& operator=(const DynamicMapField&) = delete;
702   ~DynamicMapField();
703 
704  private:
705   friend class MapFieldBase;
706 
707   const Message* default_entry_;
708 
709   static const VTable kVTable;
710 
711   void AllocateMapValue(MapValueRef* map_val);
712 
713   static void MergeFromImpl(MapFieldBase& base, const MapFieldBase& other);
714   static bool InsertOrLookupMapValueNoSyncImpl(MapFieldBase& base,
715                                                const MapKey& map_key,
716                                                MapValueRef* val);
717   static void ClearMapNoSyncImpl(MapFieldBase& base);
718 
719   static void UnsafeShallowSwapImpl(MapFieldBase& lhs, MapFieldBase& rhs) {
720     static_cast<DynamicMapField&>(lhs).Swap(
721         static_cast<DynamicMapField*>(&rhs));
722   }
723 
724   static size_t SpaceUsedExcludingSelfNoLockImpl(const MapFieldBase& map);
725 
726   static const Message* GetPrototypeImpl(const MapFieldBase& map);
727 };
728 
729 }  // namespace internal
730 
731 // MapValueConstRef points to a map value. Users can NOT modify
732 // the map value.
733 class PROTOBUF_EXPORT MapValueConstRef {
734  public:
735   MapValueConstRef() : data_(nullptr), type_() {}
736 
737   int64_t GetInt64Value() const {
738     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64,
739                "MapValueConstRef::GetInt64Value");
740     return *reinterpret_cast<int64_t*>(data_);
741   }
742   uint64_t GetUInt64Value() const {
743     TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64,
744                "MapValueConstRef::GetUInt64Value");
745     return *reinterpret_cast<uint64_t*>(data_);
746   }
747   int32_t GetInt32Value() const {
748     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32,
749                "MapValueConstRef::GetInt32Value");
750     return *reinterpret_cast<int32_t*>(data_);
751   }
752   uint32_t GetUInt32Value() const {
753     TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32,
754                "MapValueConstRef::GetUInt32Value");
755     return *reinterpret_cast<uint32_t*>(data_);
756   }
757   bool GetBoolValue() const {
758     TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueConstRef::GetBoolValue");
759     return *reinterpret_cast<bool*>(data_);
760   }
761   int GetEnumValue() const {
762     TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueConstRef::GetEnumValue");
763     return *reinterpret_cast<int*>(data_);
764   }
765   const std::string& GetStringValue() const {
766     TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING,
767                "MapValueConstRef::GetStringValue");
768     return *reinterpret_cast<std::string*>(data_);
769   }
770   float GetFloatValue() const {
771     TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT,
772                "MapValueConstRef::GetFloatValue");
773     return *reinterpret_cast<float*>(data_);
774   }
775   double GetDoubleValue() const {
776     TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE,
777                "MapValueConstRef::GetDoubleValue");
778     return *reinterpret_cast<double*>(data_);
779   }
780 
781   const Message& GetMessageValue() const {
782     TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
783                "MapValueConstRef::GetMessageValue");
784     return *reinterpret_cast<Message*>(data_);
785   }
786 
787   FieldDescriptor::CppType type() const {
788     if (type_ == FieldDescriptor::CppType() || data_ == nullptr) {
789       ABSL_LOG(FATAL)
790           << "Protocol Buffer map usage error:\n"
791           << "MapValueConstRef::type MapValueConstRef is not initialized.";
792     }
793     return type_;
794   }
795 
796  protected:
797   // data_ point to a map value. MapValueConstRef does not
798   // own this value.
799   void* data_;
800   // type_ is 0 or a valid FieldDescriptor::CppType.
801   // Use "CppType()" to indicate zero.
802   FieldDescriptor::CppType type_;
803 
804  private:
805   template <typename Derived, typename K, typename V,
806             internal::WireFormatLite::FieldType key_wire_type,
807             internal::WireFormatLite::FieldType value_wire_type>
808   friend class internal::MapField;
809   template <typename K, typename V>
810   friend class internal::TypeDefinedMapFieldBase;
811   friend class google::protobuf::MapIterator;
812   friend class Reflection;
813   friend class internal::DynamicMapField;
814   friend class internal::MapFieldBase;
815 
816   void SetValueOrCopy(const void* val) { SetValue(val); }
817   void SetValueOrCopy(const MapValueConstRef* val) { CopyFrom(*val); }
818 
819   void SetType(FieldDescriptor::CppType type) { type_ = type; }
820   void SetValue(const void* val) { data_ = const_cast<void*>(val); }
821   void CopyFrom(const MapValueConstRef& other) {
822     type_ = other.type_;
823     data_ = other.data_;
824   }
825 };
826 
827 // MapValueRef points to a map value. Users are able to modify
828 // the map value.
829 class PROTOBUF_EXPORT MapValueRef final : public MapValueConstRef {
830  public:
831   MapValueRef() = default;
832 
833   void SetInt64Value(int64_t value) {
834     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT64, "MapValueRef::SetInt64Value");
835     *reinterpret_cast<int64_t*>(data_) = value;
836   }
837   void SetUInt64Value(uint64_t value) {
838     TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT64, "MapValueRef::SetUInt64Value");
839     *reinterpret_cast<uint64_t*>(data_) = value;
840   }
841   void SetInt32Value(int32_t value) {
842     TYPE_CHECK(FieldDescriptor::CPPTYPE_INT32, "MapValueRef::SetInt32Value");
843     *reinterpret_cast<int32_t*>(data_) = value;
844   }
845   void SetUInt32Value(uint32_t value) {
846     TYPE_CHECK(FieldDescriptor::CPPTYPE_UINT32, "MapValueRef::SetUInt32Value");
847     *reinterpret_cast<uint32_t*>(data_) = value;
848   }
849   void SetBoolValue(bool value) {
850     TYPE_CHECK(FieldDescriptor::CPPTYPE_BOOL, "MapValueRef::SetBoolValue");
851     *reinterpret_cast<bool*>(data_) = value;
852   }
853   // TODO - Checks that enum is member.
854   void SetEnumValue(int value) {
855     TYPE_CHECK(FieldDescriptor::CPPTYPE_ENUM, "MapValueRef::SetEnumValue");
856     *reinterpret_cast<int*>(data_) = value;
857   }
858   void SetStringValue(const std::string& value) {
859     TYPE_CHECK(FieldDescriptor::CPPTYPE_STRING, "MapValueRef::SetStringValue");
860     *reinterpret_cast<std::string*>(data_) = value;
861   }
862   void SetFloatValue(float value) {
863     TYPE_CHECK(FieldDescriptor::CPPTYPE_FLOAT, "MapValueRef::SetFloatValue");
864     *reinterpret_cast<float*>(data_) = value;
865   }
866   void SetDoubleValue(double value) {
867     TYPE_CHECK(FieldDescriptor::CPPTYPE_DOUBLE, "MapValueRef::SetDoubleValue");
868     *reinterpret_cast<double*>(data_) = value;
869   }
870 
871   Message* MutableMessageValue() {
872     TYPE_CHECK(FieldDescriptor::CPPTYPE_MESSAGE,
873                "MapValueRef::MutableMessageValue");
874     return reinterpret_cast<Message*>(data_);
875   }
876 
877  private:
878   friend class internal::DynamicMapField;
879 
880   // Only used in DynamicMapField
881   void DeleteData() {
882     switch (type_) {
883 #define HANDLE_TYPE(CPPTYPE, TYPE)           \
884   case FieldDescriptor::CPPTYPE_##CPPTYPE: { \
885     delete reinterpret_cast<TYPE*>(data_);   \
886     break;                                   \
887   }
888       HANDLE_TYPE(INT32, int32_t);
889       HANDLE_TYPE(INT64, int64_t);
890       HANDLE_TYPE(UINT32, uint32_t);
891       HANDLE_TYPE(UINT64, uint64_t);
892       HANDLE_TYPE(DOUBLE, double);
893       HANDLE_TYPE(FLOAT, float);
894       HANDLE_TYPE(BOOL, bool);
895       HANDLE_TYPE(STRING, std::string);
896       HANDLE_TYPE(ENUM, int32_t);
897       HANDLE_TYPE(MESSAGE, Message);
898 #undef HANDLE_TYPE
899     }
900   }
901 };
902 
903 #undef TYPE_CHECK
904 
905 class PROTOBUF_EXPORT MapIterator {
906  public:
907   MapIterator(Message* message, const FieldDescriptor* field) {
908     const Reflection* reflection = message->GetReflection();
909     map_ = reflection->MutableMapData(message, field);
910     key_.SetType(field->message_type()->map_key()->cpp_type());
911     value_.SetType(field->message_type()->map_value()->cpp_type());
912   }
913   MapIterator(const MapIterator& other) { *this = other; }
914   MapIterator& operator=(const MapIterator& other) {
915     map_ = other.map_;
916     map_->CopyIterator(this, other);
917     return *this;
918   }
919   friend bool operator==(const MapIterator& a, const MapIterator& b) {
920     return a.map_->EqualIterator(a, b);
921   }
922   friend bool operator!=(const MapIterator& a, const MapIterator& b) {
923     return !a.map_->EqualIterator(a, b);
924   }
925   MapIterator& operator++() {
926     map_->IncreaseIterator(this);
927     return *this;
928   }
929   MapIterator operator++(int) {
930     // iter_ is copied from Map<...>::iterator, no need to
931     // copy from its self again. Use the same implementation
932     // with operator++()
933     map_->IncreaseIterator(this);
934     return *this;
935   }
936   const MapKey& GetKey() { return key_; }
937   const MapValueRef& GetValueRef() { return value_; }
938   MapValueRef* MutableValueRef() {
939     map_->SetMapDirty();
940     return &value_;
941   }
942 
943  private:
944   template <typename Key, typename T>
945   friend class internal::TypeDefinedMapFieldBase;
946   friend class internal::DynamicMapField;
947   template <typename Derived, typename Key, typename T,
948             internal::WireFormatLite::FieldType kKeyFieldType,
949             internal::WireFormatLite::FieldType kValueFieldType>
950   friend class internal::MapField;
951   friend class internal::MapFieldBase;
952   template <typename MessageT>
953   friend struct internal::MapDynamicFieldInfo;
954 
955   MapIterator(internal::MapFieldBase* map, const Descriptor* descriptor) {
956     map_ = map;
957     key_.SetType(descriptor->map_key()->cpp_type());
958     value_.SetType(descriptor->map_value()->cpp_type());
959   }
960 
961   internal::UntypedMapIterator iter_;
962   // Point to a MapField to call helper methods implemented in MapField.
963   // MapIterator does not own this object.
964   internal::MapFieldBase* map_;
965   MapKey key_;
966   MapValueRef value_;
967 };
968 
969 namespace internal {
970 template <>
971 struct is_internal_map_value_type<class MapValueConstRef> : std::true_type {};
972 template <>
973 struct is_internal_map_value_type<class MapValueRef> : std::true_type {};
974 }  // namespace internal
975 
976 }  // namespace protobuf
977 }  // namespace google
978 
979 #ifdef _MSC_VER
980 #pragma warning(pop)  // restore warning C4265
981 #endif                // _MSC_VER
982 
983 #include "google/protobuf/port_undef.inc"
984 
985 #endif  // GOOGLE_PROTOBUF_MAP_FIELD_H__
986