text: // 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.
  
  #ifndef GOOGLE_PROTOBUF_TYPE_HANDLER_H__
  #define GOOGLE_PROTOBUF_TYPE_HANDLER_H__
  
  #include <google/protobuf/arena.h>
  #include <google/protobuf/wire_format_lite_inl.h>
  
  namespace google {
  namespace protobuf {
  namespace internal {
  
  // Used for compile time type selection. MapIf::type will be TrueType if Flag is
  // true and FalseType otherwise.
  template<bool Flag, typename TrueType, typename FalseType>
  struct MapIf;
  
  template<typename TrueType, typename FalseType>
  struct MapIf<true, TrueType, FalseType> {
    typedef TrueType type;
  };
  
  template<typename TrueType, typename FalseType>
  struct MapIf<false, TrueType, FalseType> {
    typedef FalseType type;
  };
  
  // In proto2 Map, enum needs to be initialized to given default value, while
  // other types' default value can be inferred from the type.
  template <bool IsEnum, typename Type>
  class MapValueInitializer {
   public:
    static inline void Initialize(Type& type, int default_enum_value);
  };
  
  template <typename Type>
  class MapValueInitializer<true, Type> {
   public:
    static inline void Initialize(Type& value, int default_enum_value) {
      value = static_cast<Type>(default_enum_value);
    }
  };
  
  template <typename Type>
  class MapValueInitializer<false, Type> {
   public:
    static inline void Initialize(Type& /* value */, int /* default_enum_value */) {}
  };
  
  template <typename Type, bool is_arena_constructable>
  class MapArenaMessageCreator {
   public:
    // Use arena to create message if Type is arena constructable. Otherwise,
    // create the message on heap.
    static inline Type* CreateMessage(Arena* arena);
  };
  template <typename Type>
  class MapArenaMessageCreator<Type, true> {
   public:
    static inline Type* CreateMessage(Arena* arena) {
      return Arena::CreateMessage<Type>(arena);
    }
  };
  template <typename Type>
  class MapArenaMessageCreator<Type, false> {
   public:
    static inline Type* CreateMessage(Arena* arena) {
      return Arena::Create<Type>(arena);
    }
  };
  
  // Define constants for given wire field type
  template <WireFormatLite::FieldType field_type, typename Type>
  class MapWireFieldTypeTraits {};
  
  #define TYPE_TRAITS(FieldType, CType, WireFormatType, IsMessage, IsEnum)   \
    template <typename Type>                                                 \
    class MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, Type> {   \
     public:                                                                 \
      static const bool kIsMessage = IsMessage;                              \
      static const bool kIsEnum = IsEnum;                                    \
      typedef typename MapIf<kIsMessage, Type*, CType>::type TypeOnMemory;   \
      typedef typename MapIf<kIsEnum, int, Type>::type MapEntryAccessorType; \
      static const WireFormatLite::WireType kWireType =                      \
          WireFormatLite::WIRETYPE_##WireFormatType;                         \
    };
  
  TYPE_TRAITS(MESSAGE , Type, LENGTH_DELIMITED, true, false)
  TYPE_TRAITS(STRING  , ArenaStringPtr, LENGTH_DELIMITED, false, false)
  TYPE_TRAITS(BYTES   , ArenaStringPtr ,  LENGTH_DELIMITED, false, false)
  TYPE_TRAITS(INT64   , int64  ,  VARINT , false, false)
  TYPE_TRAITS(UINT64  , uint64 ,  VARINT , false, false)
  TYPE_TRAITS(INT32   , int32  ,  VARINT , false, false)
  TYPE_TRAITS(UINT32  , uint32 ,  VARINT , false, false)
  TYPE_TRAITS(SINT64  , int64  ,  VARINT , false, false)
  TYPE_TRAITS(SINT32  , int32  ,  VARINT , false, false)
  TYPE_TRAITS(ENUM    , int    ,  VARINT , false, true )
  TYPE_TRAITS(DOUBLE  , double ,  FIXED64, false, false)
  TYPE_TRAITS(FLOAT   , float  ,  FIXED32, false, false)
  TYPE_TRAITS(FIXED64 , uint64 ,  FIXED64, false, false)
  TYPE_TRAITS(FIXED32 , uint32 ,  FIXED32, false, false)
  TYPE_TRAITS(SFIXED64, int64  ,  FIXED64, false, false)
  TYPE_TRAITS(SFIXED32, int32  ,  FIXED32, false, false)
  TYPE_TRAITS(BOOL    , bool   ,  VARINT , false, false)
  
  #undef TYPE_TRAITS
  
  template <WireFormatLite::FieldType field_type, typename Type>
  class MapTypeHandler {};
  
  template <typename Type>
  class MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type> {
   public:
    // Enum type cannot be used for MapTypeHandler::Read. Define a type which will
    // replace Enum with int.
    typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
        Type>::MapEntryAccessorType MapEntryAccessorType;
    // Internal stored type in MapEntryLite for given wire field type.
    typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE,
                                            Type>::TypeOnMemory TypeOnMemory;
    // Corresponding wire type for field type.
    static const WireFormatLite::WireType kWireType =
        MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kWireType;
    // Whether wire type is for message.
    static const bool kIsMessage =
        MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsMessage;
    // Whether wire type is for enum.
    static const bool kIsEnum =
        MapWireFieldTypeTraits<WireFormatLite::TYPE_MESSAGE, Type>::kIsEnum;
  
    // Functions used in parsing and serialization. ===================
    static inline size_t ByteSize(const MapEntryAccessorType& value);
    static inline int GetCachedSize(const MapEntryAccessorType& value);
    static inline bool Read(io::CodedInputStream* input,
                            MapEntryAccessorType* value);
    static inline void Write(int field, const MapEntryAccessorType& value,
                             io::CodedOutputStream* output);
    static inline uint8* InternalWriteToArray(int field,
                                              const MapEntryAccessorType& value,
                                              bool deterministic, uint8* target);
    static inline uint8* WriteToArray(int field,
                                      const MapEntryAccessorType& value,
                                      uint8* target);
  
    // Functions to manipulate data on memory. ========================
    static inline const Type& GetExternalReference(const Type* value);
    static inline void DeleteNoArena(const Type* x);
    static inline void Merge(const Type& from, Type** to, Arena* arena);
    static inline void Clear(Type** value, Arena* arena);
    static inline void ClearMaybeByDefaultEnum(Type** value, Arena* arena,
                                               int default_enum_value);
    static inline void Initialize(Type** x, Arena* arena);
  
    static inline void InitializeMaybeByDefaultEnum(Type** x,
                                                    int default_enum_value,
                                                    Arena* arena);
    static inline Type* EnsureMutable(Type** value, Arena* arena);
    // SpaceUsedInMapEntry: Return bytes used by value in MapEntry, excluding
    // those already calculate in sizeof(MapField).
    static inline size_t SpaceUsedInMapEntryLong(const Type* value);
    // Return bytes used by value in Map.
    static inline size_t SpaceUsedInMapLong(const Type& value);
    // Assign default value to given instance.
    static inline void AssignDefaultValue(Type** value);
    // Return default instance if value is not initialized when calling const
    // reference accessor.
    static inline const Type& DefaultIfNotInitialized(
        const Type* value, const Type* default_value);
    // Check if all required fields have values set.
    static inline bool IsInitialized(Type* value);
  };
  
  #define MAP_HANDLER(FieldType)                                                \
    template <typename Type>                                                    \
    class MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type> {              \
     public:                                                                    \
      typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
                                              Type>::MapEntryAccessorType       \
          MapEntryAccessorType;                                                 \
      typedef typename MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType, \
                                              Type>::TypeOnMemory TypeOnMemory; \
      static const WireFormatLite::WireType kWireType =                         \
          MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType,              \
                                 Type>::kWireType;                              \
      static const bool kIsMessage =                                            \
          MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType,              \
                                 Type>::kIsMessage;                             \
      static const bool kIsEnum =                                               \
          MapWireFieldTypeTraits<WireFormatLite::TYPE_##FieldType,              \
                                 Type>::kIsEnum;                                \
      static inline int ByteSize(const MapEntryAccessorType& value);            \
      static inline int GetCachedSize(const MapEntryAccessorType& value);       \
      static inline bool Read(io::CodedInputStream* input,                      \
                              MapEntryAccessorType* value);                     \
      static inline void Write(int field, const MapEntryAccessorType& value,    \
                               io::CodedOutputStream* output);                  \
      static inline uint8* InternalWriteToArray(                                \
          int field, const MapEntryAccessorType& value, bool deterministic,     \
          uint8* target);                                                       \
      static inline uint8* WriteToArray(int field,                              \
                                        const MapEntryAccessorType& value,      \
                                        uint8* target) {                        \
        return InternalWriteToArray(field, value, false, target);               \
      }                                                                         \
      static inline const MapEntryAccessorType& GetExternalReference(           \
          const TypeOnMemory& value);                                           \
      static inline void DeleteNoArena(const TypeOnMemory& x);                  \
      static inline void Merge(const MapEntryAccessorType& from,                \
                               TypeOnMemory* to, Arena* arena);                 \
      static inline void Clear(TypeOnMemory* value, Arena* arena);              \
      static inline void ClearMaybeByDefaultEnum(TypeOnMemory* value,           \
                                                 Arena* arena,                  \
                                                 int default_enum);             \
      static inline size_t SpaceUsedInMapEntryLong(const TypeOnMemory& value);  \
      static inline size_t SpaceUsedInMapLong(const TypeOnMemory& value);       \
      static inline size_t SpaceUsedInMapLong(const string& value);             \
      static inline void AssignDefaultValue(TypeOnMemory* value);               \
      static inline const MapEntryAccessorType& DefaultIfNotInitialized(        \
          const TypeOnMemory& value, const TypeOnMemory& default_value);        \
      static inline bool IsInitialized(const TypeOnMemory& value);              \
      static void DeleteNoArena(TypeOnMemory& value);                           \
      static inline void Initialize(TypeOnMemory* value, Arena* arena);         \
      static inline void InitializeMaybeByDefaultEnum(TypeOnMemory* value,      \
                                                      int default_enum_value,   \
                                                      Arena* arena);            \
      static inline MapEntryAccessorType* EnsureMutable(TypeOnMemory* value,    \
                                                        Arena* arena);          \
    };
  MAP_HANDLER(STRING)
  MAP_HANDLER(BYTES)
  MAP_HANDLER(INT64)
  MAP_HANDLER(UINT64)
  MAP_HANDLER(INT32)
  MAP_HANDLER(UINT32)
  MAP_HANDLER(SINT64)
  MAP_HANDLER(SINT32)
  MAP_HANDLER(ENUM)
  MAP_HANDLER(DOUBLE)
  MAP_HANDLER(FLOAT)
  MAP_HANDLER(FIXED64)
  MAP_HANDLER(FIXED32)
  MAP_HANDLER(SFIXED64)
  MAP_HANDLER(SFIXED32)
  MAP_HANDLER(BOOL)
  #undef MAP_HANDLER
  
  template <typename Type>
  inline size_t
  MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::ByteSize(
      const MapEntryAccessorType& value) {
    return WireFormatLite::MessageSizeNoVirtual(value);
  }
  
  #define GOOGLE_PROTOBUF_BYTE_SIZE(FieldType, DeclaredType)                     \
    template <typename Type>                                                     \
    inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
        const MapEntryAccessorType& value) {                                     \
      return static_cast<int>(WireFormatLite::DeclaredType##Size(value));        \
    }
  
  GOOGLE_PROTOBUF_BYTE_SIZE(STRING, String)
  GOOGLE_PROTOBUF_BYTE_SIZE(BYTES , Bytes)
  GOOGLE_PROTOBUF_BYTE_SIZE(INT64 , Int64)
  GOOGLE_PROTOBUF_BYTE_SIZE(UINT64, UInt64)
  GOOGLE_PROTOBUF_BYTE_SIZE(INT32 , Int32)
  GOOGLE_PROTOBUF_BYTE_SIZE(UINT32, UInt32)
  GOOGLE_PROTOBUF_BYTE_SIZE(SINT64, SInt64)
  GOOGLE_PROTOBUF_BYTE_SIZE(SINT32, SInt32)
  GOOGLE_PROTOBUF_BYTE_SIZE(ENUM  , Enum)
  
  #undef GOOGLE_PROTOBUF_BYTE_SIZE
  
  #define FIXED_BYTE_SIZE(FieldType, DeclaredType)                               \
    template <typename Type>                                                     \
    inline int MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::ByteSize( \
        const MapEntryAccessorType& /* value */) {                               \
      return WireFormatLite::k##DeclaredType##Size;                              \
    }
  
  FIXED_BYTE_SIZE(DOUBLE  , Double)
  FIXED_BYTE_SIZE(FLOAT   , Float)
  FIXED_BYTE_SIZE(FIXED64 , Fixed64)
  FIXED_BYTE_SIZE(FIXED32 , Fixed32)
  FIXED_BYTE_SIZE(SFIXED64, SFixed64)
  FIXED_BYTE_SIZE(SFIXED32, SFixed32)
  FIXED_BYTE_SIZE(BOOL    , Bool)
  
  #undef FIXED_BYTE_SIZE
  
  template <typename Type>
  inline int
  MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::GetCachedSize(
      const MapEntryAccessorType& value) {
    return static_cast<int>(
        WireFormatLite::LengthDelimitedSize(
            static_cast<size_t>(value.GetCachedSize())));
  }
  
  #define GET_CACHED_SIZE(FieldType, DeclaredType)                         \
    template <typename Type>                                               \
    inline int                                                             \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
        const MapEntryAccessorType& value) {                               \
      return static_cast<int>(WireFormatLite::DeclaredType##Size(value));  \
    }
  
  GET_CACHED_SIZE(STRING, String)
  GET_CACHED_SIZE(BYTES , Bytes)
  GET_CACHED_SIZE(INT64 , Int64)
  GET_CACHED_SIZE(UINT64, UInt64)
  GET_CACHED_SIZE(INT32 , Int32)
  GET_CACHED_SIZE(UINT32, UInt32)
  GET_CACHED_SIZE(SINT64, SInt64)
  GET_CACHED_SIZE(SINT32, SInt32)
  GET_CACHED_SIZE(ENUM  , Enum)
  
  #undef GET_CACHED_SIZE
  
  #define GET_FIXED_CACHED_SIZE(FieldType, DeclaredType)                   \
    template <typename Type>                                               \
    inline int                                                             \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::GetCachedSize( \
        const MapEntryAccessorType& /* value */) {                         \
      return WireFormatLite::k##DeclaredType##Size;                        \
    }
  
  GET_FIXED_CACHED_SIZE(DOUBLE  , Double)
  GET_FIXED_CACHED_SIZE(FLOAT   , Float)
  GET_FIXED_CACHED_SIZE(FIXED64 , Fixed64)
  GET_FIXED_CACHED_SIZE(FIXED32 , Fixed32)
  GET_FIXED_CACHED_SIZE(SFIXED64, SFixed64)
  GET_FIXED_CACHED_SIZE(SFIXED32, SFixed32)
  GET_FIXED_CACHED_SIZE(BOOL    , Bool)
  
  #undef GET_FIXED_CACHED_SIZE
  
  template <typename Type>
  inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Write(
      int field, const MapEntryAccessorType& value,
      io::CodedOutputStream* output) {
    WireFormatLite::WriteMessageMaybeToArray(field, value, output);
  }
  
  template <typename Type>
  inline uint8*
  MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::InternalWriteToArray(
      int field, const MapEntryAccessorType& value, bool deterministic,
      uint8* target) {
    return WireFormatLite::InternalWriteMessageToArray(field, value,
                                                       deterministic, target);
  }
  
  #define WRITE_METHOD(FieldType, DeclaredType)                                  \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Write(   \
        int field, const MapEntryAccessorType& value,                            \
        io::CodedOutputStream* output) {                                         \
      return WireFormatLite::Write##DeclaredType(field, value, output);          \
    }                                                                            \
    template <typename Type>                                                     \
    inline uint8*                                                                \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::InternalWriteToArray(                                  \
        int field, const MapEntryAccessorType& value, bool, uint8* target) {     \
      return WireFormatLite::Write##DeclaredType##ToArray(field, value, target); \
    }
  
  WRITE_METHOD(STRING  , String)
  WRITE_METHOD(BYTES   , Bytes)
  WRITE_METHOD(INT64   , Int64)
  WRITE_METHOD(UINT64  , UInt64)
  WRITE_METHOD(INT32   , Int32)
  WRITE_METHOD(UINT32  , UInt32)
  WRITE_METHOD(SINT64  , SInt64)
  WRITE_METHOD(SINT32  , SInt32)
  WRITE_METHOD(ENUM    , Enum)
  WRITE_METHOD(DOUBLE  , Double)
  WRITE_METHOD(FLOAT   , Float)
  WRITE_METHOD(FIXED64 , Fixed64)
  WRITE_METHOD(FIXED32 , Fixed32)
  WRITE_METHOD(SFIXED64, SFixed64)
  WRITE_METHOD(SFIXED32, SFixed32)
  WRITE_METHOD(BOOL    , Bool)
  
  #undef WRITE_METHOD
  
  template <typename Type>
  inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Read(
      io::CodedInputStream* input, MapEntryAccessorType* value) {
    return WireFormatLite::ReadMessageNoVirtual(input, value);
  }
  
  template <typename Type>
  inline bool MapTypeHandler<WireFormatLite::TYPE_STRING, Type>::Read(
      io::CodedInputStream* input, MapEntryAccessorType* value) {
    return WireFormatLite::ReadString(input, value);
  }
  
  template <typename Type>
  inline bool MapTypeHandler<WireFormatLite::TYPE_BYTES, Type>::Read(
      io::CodedInputStream* input, MapEntryAccessorType* value) {
    return WireFormatLite::ReadBytes(input, value);
  }
  
  #define READ_METHOD(FieldType)                                              \
    template <typename Type>                                                  \
    inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Read( \
        io::CodedInputStream* input, MapEntryAccessorType* value) {           \
      return WireFormatLite::ReadPrimitive<TypeOnMemory,                      \
                                           WireFormatLite::TYPE_##FieldType>( \
          input, value);                                                      \
    }
  
  READ_METHOD(INT64)
  READ_METHOD(UINT64)
  READ_METHOD(INT32)
  READ_METHOD(UINT32)
  READ_METHOD(SINT64)
  READ_METHOD(SINT32)
  READ_METHOD(ENUM)
  READ_METHOD(DOUBLE)
  READ_METHOD(FLOAT)
  READ_METHOD(FIXED64)
  READ_METHOD(FIXED32)
  READ_METHOD(SFIXED64)
  READ_METHOD(SFIXED32)
  READ_METHOD(BOOL)
  
  #undef READ_METHOD
  
  // Definition for message handler
  
  template <typename Type>
  inline const Type&
  MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                          Type>::GetExternalReference(const Type* value) {
    return *value;
  }
  
  template <typename Type>
  inline size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                               Type>::SpaceUsedInMapEntryLong(const Type* value) {
    return value->SpaceUsedLong();
  }
  
  template <typename Type>
  size_t MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::SpaceUsedInMapLong(
      const Type& value) {
    return value.SpaceUsedLong();
  }
  
  template <typename Type>
  inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Clear(
      Type** value, Arena* /* arena */) {
    if (*value != NULL) (*value)->Clear();
  }
  template <typename Type>
  inline void
  MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                          Type>::ClearMaybeByDefaultEnum(Type** value,
                                                         Arena* /* arena */,
                                                         int /* default_enum_value */) {
    if (*value != NULL) (*value)->Clear();
  }
  template <typename Type>
  inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::Merge(
      const Type& from, Type** to, Arena* /* arena */) {
    (*to)->MergeFrom(from);
  }
  
  template <typename Type>
  void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::DeleteNoArena(
      const Type* ptr) {
    delete ptr;
  }
  
  template <typename Type>
  inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                                      Type>::AssignDefaultValue(Type** value) {
    *value = const_cast<Type*>(Type::internal_default_instance());
  }
  
  template <typename Type>
  inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                                      Type>::Initialize(Type** x,
                                                        Arena* /* arena */) {
    *x = NULL;
  }
  
  template <typename Type>
  inline void MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
      InitializeMaybeByDefaultEnum(Type** x, int /* default_enum_value */,
                                   Arena* /* arena */) {
    *x = NULL;
  }
  
  template <typename Type>
  inline Type* MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                                       Type>::EnsureMutable(Type** value,
                                                            Arena* arena) {
    if (*value == NULL) {
      *value =
          MapArenaMessageCreator<Type, Arena::is_arena_constructable<Type>::
                                           type::value>::CreateMessage(arena);
    }
    return *value;
  }
  
  template <typename Type>
  inline const Type& MapTypeHandler<WireFormatLite::TYPE_MESSAGE, Type>::
      DefaultIfNotInitialized(const Type* value, const Type* default_value) {
    return value != NULL ? *value : *default_value;
  }
  
  template <typename Type>
  inline bool MapTypeHandler<WireFormatLite::TYPE_MESSAGE,
                                      Type>::IsInitialized(Type* value) {
    return value->IsInitialized();
  }
  
  // Definition for string/bytes handler
  
  #define STRING_OR_BYTES_HANDLER_FUNCTIONS(FieldType)                           \
    template <typename Type>                                                     \
    inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,       \
                                         Type>::MapEntryAccessorType&            \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::GetExternalReference(const TypeOnMemory& value) {      \
      return value.Get();                                                        \
    }                                                                            \
    template <typename Type>                                                     \
    inline size_t                                                                \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& value) {   \
      return sizeof(value);                                                      \
    }                                                                            \
    template <typename Type>                                                     \
    inline size_t                                                                \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong(  \
        const TypeOnMemory& value) {                                             \
      return sizeof(value);                                                      \
    }                                                                            \
    template <typename Type>                                                     \
    inline size_t                                                                \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong(  \
        const string& value) {                                                   \
      return sizeof(value);                                                      \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear(   \
        TypeOnMemory* value, Arena* arena) {                                     \
      value->ClearToEmpty(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),    \
                          arena);                                                \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
        ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* arena,               \
                                int /* default_enum */) {                        \
      Clear(value, arena);                                                       \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge(   \
        const MapEntryAccessorType& from, TypeOnMemory* to, Arena* arena) {      \
      to->Set(&::google::protobuf::internal::GetEmptyStringAlreadyInited(), from, arena);  \
    }                                                                            \
    template <typename Type>                                                     \
    void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::DeleteNoArena(  \
        TypeOnMemory& value) {                                                   \
      value.DestroyNoArena(&::google::protobuf::internal::GetEmptyStringAlreadyInited());  \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
                               Type>::AssignDefaultValue(TypeOnMemory* /* value */) {} \
    template <typename Type>                                                     \
    inline void                                                                  \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize(          \
        TypeOnMemory* value, Arena* /* arena */) {                               \
      value->UnsafeSetDefault(                                                   \
          &::google::protobuf::internal::GetEmptyStringAlreadyInited());                   \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
        InitializeMaybeByDefaultEnum(TypeOnMemory* value,                        \
                                     int /* default_enum_value */,               \
                                     Arena* arena) {                             \
      Initialize(value, arena);                                                  \
    }                                                                            \
    template <typename Type>                                                     \
    inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,             \
                                   Type>::MapEntryAccessorType*                  \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable(       \
        TypeOnMemory* value, Arena* arena) {                                     \
      return value->Mutable(&::google::protobuf::internal::GetEmptyStringAlreadyInited(),  \
                            arena);                                              \
    }                                                                            \
    template <typename Type>                                                     \
    inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,       \
                                         Type>::MapEntryAccessorType&            \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::DefaultIfNotInitialized(const TypeOnMemory& value,     \
                                                  const TypeOnMemory&            \
                                                      /* default_value */) {     \
      return value.Get();                                                        \
    }                                                                            \
    template <typename Type>                                                     \
    inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
                               Type>::IsInitialized(const TypeOnMemory& /* value */) { \
      return true;                                                               \
    }
  STRING_OR_BYTES_HANDLER_FUNCTIONS(STRING)
  STRING_OR_BYTES_HANDLER_FUNCTIONS(BYTES)
  #undef STRING_OR_BYTES_HANDLER_FUNCTIONS
  
  #define PRIMITIVE_HANDLER_FUNCTIONS(FieldType)                                 \
    template <typename Type>                                                     \
    inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,       \
                                         Type>::MapEntryAccessorType&            \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::GetExternalReference(const TypeOnMemory& value) {      \
      return value;                                                              \
    }                                                                            \
    template <typename Type>                                                     \
    inline size_t                                                                \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::SpaceUsedInMapEntryLong(const TypeOnMemory& /* value */) {   \
      return 0;                                                                  \
    }                                                                            \
    template <typename Type>                                                     \
    inline size_t                                                                \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::SpaceUsedInMapLong(  \
        const TypeOnMemory& /* value */) {                                       \
      return sizeof(Type);                                                       \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Clear(   \
        TypeOnMemory* value, Arena* /* arena */) {                               \
      *value = 0;                                                                \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
        ClearMaybeByDefaultEnum(TypeOnMemory* value, Arena* /* arena */,         \
                                int default_enum_value) {                        \
      *value = static_cast<TypeOnMemory>(default_enum_value);                    \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Merge(   \
        const MapEntryAccessorType& from, TypeOnMemory* to,                      \
        Arena* /* arena */) {                                                    \
      *to = from;                                                                \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
                               Type>::DeleteNoArena(TypeOnMemory& /* x */) {}    \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
                               Type>::AssignDefaultValue(TypeOnMemory* /* value */) {} \
    template <typename Type>                                                     \
    inline void                                                                  \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::Initialize(          \
        TypeOnMemory* value, Arena* /* arena */) {                               \
      *value = 0;                                                                \
    }                                                                            \
    template <typename Type>                                                     \
    inline void MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::         \
        InitializeMaybeByDefaultEnum(TypeOnMemory* value,                        \
                                     int default_enum_value,                     \
                                     Arena* /* arena */) {                       \
      *value = static_cast<TypeOnMemory>(default_enum_value);                    \
    }                                                                            \
    template <typename Type>                                                     \
    inline typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,             \
                                   Type>::MapEntryAccessorType*                  \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType, Type>::EnsureMutable(       \
        TypeOnMemory* value, Arena* /* arena */) {                               \
      return value;                                                              \
    }                                                                            \
    template <typename Type>                                                     \
    inline const typename MapTypeHandler<WireFormatLite::TYPE_##FieldType,       \
                                         Type>::MapEntryAccessorType&            \
    MapTypeHandler<WireFormatLite::TYPE_##FieldType,                             \
                   Type>::DefaultIfNotInitialized(const TypeOnMemory& value,     \
                                                  const TypeOnMemory&            \
                                                     /* default_value */) {      \
      return value;                                                              \
    }                                                                            \
    template <typename Type>                                                     \
    inline bool MapTypeHandler<WireFormatLite::TYPE_##FieldType,                 \
                               Type>::IsInitialized(const TypeOnMemory& /* value */) { \
      return true;                                                               \
    }
  PRIMITIVE_HANDLER_FUNCTIONS(INT64)
  PRIMITIVE_HANDLER_FUNCTIONS(UINT64)
  PRIMITIVE_HANDLER_FUNCTIONS(INT32)
  PRIMITIVE_HANDLER_FUNCTIONS(UINT32)
  PRIMITIVE_HANDLER_FUNCTIONS(SINT64)
  PRIMITIVE_HANDLER_FUNCTIONS(SINT32)
  PRIMITIVE_HANDLER_FUNCTIONS(ENUM)
  PRIMITIVE_HANDLER_FUNCTIONS(DOUBLE)
  PRIMITIVE_HANDLER_FUNCTIONS(FLOAT)
  PRIMITIVE_HANDLER_FUNCTIONS(FIXED64)
  PRIMITIVE_HANDLER_FUNCTIONS(FIXED32)
  PRIMITIVE_HANDLER_FUNCTIONS(SFIXED64)
  PRIMITIVE_HANDLER_FUNCTIONS(SFIXED32)
  PRIMITIVE_HANDLER_FUNCTIONS(BOOL)
  #undef PRIMITIVE_HANDLER_FUNCTIONS
  
  }  // namespace internal
  }  // namespace protobuf
  
  }  // namespace google
  #endif  // GOOGLE_PROTOBUF_TYPE_HANDLER_H__
  