//
// Note that we have received an exception from c-style-artiters regarding
// dynamic_cast<> in this file:
// https://groups.google.com/a/google.com/d/msg/c-style/7Zp_XCX0e7s/I6dpzno4l-MJ
//
// IMPORTANT NOTE!  This file is compiled TWICE, once with UPB_GOOGLE3 defined
// and once without!  This allows us to provide functionality against proto2
// and protobuf opensource both in a single binary without the two conflicting.
// However we must be careful not to violate the ODR.

#include "upb/bindings/googlepb/proto2.int.h"

#include <map>

#include "upb/def.h"
#include "upb/bindings/googlepb/proto1.int.h"
#include "upb/handlers.h"
#include "upb/shim/shim.h"
#include "upb/sink.h"

namespace {

template<typename To, typename From> To CheckDownCast(From* f) {
  assert(f == NULL || dynamic_cast<To>(f) != NULL);
  return static_cast<To>(f);
}

}

// Unconditionally evaluate, but also assert in debug mode.
#define CHKRET(x) do { bool ok = (x); UPB_UNUSED(ok); assert(ok); } while (0)

namespace upb {
namespace google_google3 { class GMR_Handlers; }
namespace google_opensource { class GMR_Handlers; }
}  // namespace upb

// BEGIN DOUBLE COMPILATION TRICKERY. //////////////////////////////////////////

#ifdef UPB_GOOGLE3

// TODO(haberman): Add public functionality to ExtensionSet for populating
// LazyFields.
#define private public
#include "net/proto2/public/extension_set.h"
#undef private

#include "net/proto2/proto/descriptor.pb.h"
#include "net/proto2/public/descriptor.h"
#include "net/proto2/public/generated_message_reflection.h"
#include "net/proto2/public/lazy_field.h"
#include "net/proto2/public/message.h"
#include "net/proto2/public/repeated_field.h"
#include "net/proto2/public/string_piece_field_support.h"

namespace goog = ::proto2;
namespace me = ::upb::google_google3;

#else

// TODO(haberman): remove these once new versions of protobuf that "friend"
// upb are pervasive in the wild.
#define protected public
#include "google/protobuf/repeated_field.h"
#undef protected

#define private public
#include "google/protobuf/generated_message_reflection.h"
#undef private

#define private public
#include "google/protobuf/extension_set.h"
#undef private

#include "google/protobuf/descriptor.h"
#include "google/protobuf/descriptor.pb.h"
#include "google/protobuf/message.h"

namespace goog = ::google::protobuf;
namespace me = ::upb::google_opensource;

using goog::int32;
using goog::int64;
using goog::uint32;
using goog::uint64;
using goog::scoped_ptr;

#endif  // ifdef UPB_GOOGLE3

// END DOUBLE COMPILATION TRICKERY. ////////////////////////////////////////////

// Have to define this manually since older versions of proto2 didn't define
// an enum value for STRING.
#define UPB_CTYPE_STRING 0

template <class T> static T* GetPointer(void* message, size_t offset) {
  return reinterpret_cast<T*>(static_cast<char*>(message) + offset);
}
template <class T>
static const T* GetConstPointer(const void* message, size_t offset) {
  return reinterpret_cast<const T*>(static_cast<const char*>(message) + offset);
}

// This class contains handlers that can write into a proto2 class whose
// reflection class is GeneratedMessageReflection.  (Despite the name, even
// DynamicMessage uses GeneratedMessageReflection, so this covers all proto2
// messages generated by the compiler.)  To do this it must break the
// encapsulation of GeneratedMessageReflection and therefore depends on
// internal interfaces that are not guaranteed to be stable.  This class will
// need to be updated if any non-backward-compatible changes are made to
// GeneratedMessageReflection.
class me::GMR_Handlers {
 public:
  // Returns true if we were able to set an accessor and any other properties
  // of the FieldDef that are necessary to read/write this field to a
  // proto2::Message.
  static bool TrySet(const goog::FieldDescriptor* proto2_f,
                     const goog::Message& m, const upb::FieldDef* upb_f,
                     upb::Handlers* h) {
    const goog::Reflection* base_r = m.GetReflection();
    // See file comment re: dynamic_cast.
    const goog::internal::GeneratedMessageReflection* r =
        dynamic_cast<const goog::internal::GeneratedMessageReflection*>(base_r);
    if (!r) return false;

#define PRIMITIVE_TYPE(cpptype, cident)                                        \
case goog::FieldDescriptor::cpptype:                                           \
  SetPrimitiveHandlers<cident>(proto2_f, r, upb_f, h);                         \
  return true;

    switch (proto2_f->cpp_type()) {
      PRIMITIVE_TYPE(CPPTYPE_INT32, int32);
      PRIMITIVE_TYPE(CPPTYPE_INT64, int64);
      PRIMITIVE_TYPE(CPPTYPE_UINT32, uint32);
      PRIMITIVE_TYPE(CPPTYPE_UINT64, uint64);
      PRIMITIVE_TYPE(CPPTYPE_DOUBLE, double);
      PRIMITIVE_TYPE(CPPTYPE_FLOAT, float);
      PRIMITIVE_TYPE(CPPTYPE_BOOL, bool);
      case goog::FieldDescriptor::CPPTYPE_ENUM:
        if (proto2_f->is_extension()) {
          SetEnumExtensionHandlers(proto2_f, r, upb_f, h);
        } else {
          SetEnumHandlers(proto2_f, r, upb_f, h);
        }
        return true;
      case goog::FieldDescriptor::CPPTYPE_STRING: {
        if (proto2_f->is_extension()) {
#ifdef UPB_GOOGLE3
          SetStringExtensionHandlers<string>(proto2_f, r, upb_f, h);
#else
          SetStringExtensionHandlers<std::string>(proto2_f, r, upb_f, h);
#endif
          return true;
        }

        // Old versions of the open-source protobuf release erroneously default
        // to Cord even though that has never been supported in the open-source
        // release.
        int32_t ctype = proto2_f->options().has_ctype() ?
                        proto2_f->options().ctype()
                        : UPB_CTYPE_STRING;
        switch (ctype) {
#ifdef UPB_GOOGLE3
          case goog::FieldOptions::STRING:
            SetStringHandlers<string>(proto2_f, r, upb_f, h);
            return true;
          case goog::FieldOptions::CORD:
            SetCordHandlers(proto2_f, r, upb_f, h);
            return true;
          case goog::FieldOptions::STRING_PIECE:
            SetStringPieceHandlers(proto2_f, r, upb_f, h);
            return true;
#else
          case UPB_CTYPE_STRING:
            SetStringHandlers<std::string>(proto2_f, r, upb_f, h);
            return true;
#endif
          default:
            return false;
        }
      }
      case goog::FieldDescriptor::CPPTYPE_MESSAGE:
#ifdef UPB_GOOGLE3
        if (proto2_f->options().lazy() &&
            // proto2 lets you set lazy=true on a repeated field, but doesn't
            // actually support lazy repeated messages, so just ignore
            // lazy=true for repeated messages.
            !proto2_f->is_repeated()) {
          // Supports lazy fields and lazy extensions.
          SetLazyFieldHandlers(proto2_f, m, r, upb_f, h);
          return true;
        }
#endif
        if (proto2_f->is_extension()) {
          SetSubMessageExtensionHandlers(proto2_f, m, r, upb_f, h);
          return true;
        }
        SetSubMessageHandlers(proto2_f, m, r, upb_f, h);
        return true;
      default:
        return false;
    }
  }

#undef PRIMITIVE_TYPE

  static const goog::Message* GetFieldPrototype(
      const goog::Message& m, const goog::FieldDescriptor* f) {
    // We assume that all submessages (and extensions) will be constructed
    // using the same MessageFactory as this message.  This doesn't cover the
    // case of CodedInputStream::SetExtensionRegistry().
    // See file comment re: dynamic_cast.
    const goog::internal::GeneratedMessageReflection* r =
        dynamic_cast<const goog::internal::GeneratedMessageReflection*>(
            m.GetReflection());
    if (!r) return NULL;
    return r->message_factory_->GetPrototype(f->message_type());
  }

 private:
  static upb_selector_t GetSelector(const upb::FieldDef* f,
                                    upb::Handlers::Type type) {
    upb::Handlers::Selector selector;
    bool ok = upb::Handlers::GetSelector(f, type, &selector);
    UPB_ASSERT_VAR(ok, ok);
    return selector;
  }

  static int64_t GetHasbit(
      const goog::FieldDescriptor* f,
      const goog::internal::GeneratedMessageReflection* r) {
    // proto2 does not store hasbits for repeated fields.
    assert(!f->is_repeated());
    return (r->has_bits_offset_ * 8) + f->index();
  }

#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
  static size_t GetOneofDiscriminantOffset(
      const goog::FieldDescriptor* f,
      const goog::internal::GeneratedMessageReflection* r) {
    assert(f->containing_oneof());
    return r->oneof_case_offset_ + f->containing_oneof()->index();
  }
#endif

  static uint16_t GetOffset(
      const goog::FieldDescriptor* f,
      const goog::internal::GeneratedMessageReflection* r) {
    int index = f->index();
#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
    if (f->containing_oneof()) {
      index =
          f->containing_type()->field_count() + f->containing_oneof()->index();
    }
#endif
    return r->offsets_[index];
  }

  // Base class that provides access to elements of the message as a whole, such
  // as the unknown-field set, and is inherited by context classes for specific
  // field handlers.
  class FieldDataBase {
   public:
    FieldDataBase(const goog::internal::GeneratedMessageReflection* r)
        : unknown_fields_offset_(r->unknown_fields_offset_)
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
        , arena_offset_(r->arena_offset_)
#endif  // GOOGLE_PROTOBUF_HAS_ARENAS
    {}

#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    goog::Arena* GetArena(const goog::Message& message) const {
      if (unknown_fields_offset_ ==
          goog::internal::GeneratedMessageReflection::
          kUnknownFieldSetInMetadata) {
        const goog::internal::InternalMetadataWithArena* metadata =
            GetConstPointer<goog::internal::InternalMetadataWithArena>(
                &message, arena_offset_);
        return metadata->arena();
      } else if (arena_offset_ !=
                 goog::internal::GeneratedMessageReflection::kNoArenaPointer) {
        return *GetConstPointer<goog::Arena*>(&message, arena_offset_);
      } else {
        return NULL;
      }
    }

    goog::UnknownFieldSet* GetUnknownFieldSet(goog::Message* message) const {
      if (unknown_fields_offset_ ==
          goog::internal::GeneratedMessageReflection::
          kUnknownFieldSetInMetadata) {
        goog::internal::InternalMetadataWithArena* metadata =
            GetPointer<goog::internal::InternalMetadataWithArena>(
                message, arena_offset_);
        return metadata->mutable_unknown_fields();
      }
      return GetPointer<goog::UnknownFieldSet>(message, unknown_fields_offset_);
    }
#else  // ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    goog::UnknownFieldSet* GetUnknownFieldSet(goog::Message* message) const {
      return GetPointer<goog::UnknownFieldSet>(message, unknown_fields_offset_);
    }
#endif  // ifdef !GOOGLE_PROTOBUF_HAS_ARENAS
   private:
    int unknown_fields_offset_;
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    int arena_offset_;
#endif  // GOOGLE_PROTOBUF_HAS_ARENAS
  };

  class FieldOffset : public FieldDataBase {
   public:
    FieldOffset(const goog::FieldDescriptor* f,
                const goog::internal::GeneratedMessageReflection* r)
        : FieldDataBase(r),
          offset_(GetOffset(f, r)), is_repeated_(f->is_repeated()) {
      if (!is_repeated_) {
        int64_t hasbit = GetHasbit(f, r);
        hasbyte_ = hasbit / 8;
        mask_ = 1 << (hasbit % 8);
      }
    }

    template <class T> T* GetFieldPointer(goog::Message* message) const {
      return GetPointer<T>(message, offset_);
    }

    void SetHasbit(void* m) const {
      assert(!is_repeated_);
      uint8_t* byte = GetPointer<uint8_t>(m, hasbyte_);
      *byte |= mask_;
    }

   private:
    const size_t offset_;
    bool is_repeated_;

    // Only for non-repeated fields.
    int32_t hasbyte_;
    int8_t mask_;
  };

#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
  class OneofFieldData : public FieldDataBase {
   public:
    OneofFieldData(const goog::FieldDescriptor* f,
                   const goog::internal::GeneratedMessageReflection* r)
        : FieldDataBase(r),
          field_number_offset_(GetOneofDiscriminantOffset(f, r)),
          field_number_(f->number()) {
      const goog::OneofDescriptor* oneof = f->containing_oneof();

      // Determine the type of each discriminant value, so we know what kind of
      // value to delete if we are changing the type.
      //
      // For example, we may find that the oneof has three possible values: an
      // int32, a message, and a string.  For the int32 there is nothing to
      // delete, but the message and the string need to be deleted when we
      // switch to another oneof type, to avoid leaking it.
      //
      // TODO(haberman): share this map of types between all fields in the
      // oneof.  Right now we duplicate it for each one, which is wasteful.
      for (int i = 0; i < oneof->field_count(); i++) {
        const goog::FieldDescriptor* oneof_f = oneof->field(i);
        OneofType& type = types_[oneof_f->number()];

        switch (oneof_f->cpp_type()) {
          case goog::FieldDescriptor::CPPTYPE_STRING:
            type = GetTypeForString(oneof_f);
            break;
          case goog::FieldDescriptor::CPPTYPE_MESSAGE:
#ifdef UPB_GOOGLE3
            if (oneof_f->options().lazy()) {
              type = ONEOF_TYPE_LAZYFIELD;
              break;
            }
#endif
            type = ONEOF_TYPE_MESSAGE;
            break;

          default:
            type = ONEOF_TYPE_NONE;
            break;
        }
      }

      // "0" indicates that the field is not set.
      types_[0] = ONEOF_TYPE_NONE;
    }

    int32_t* GetFieldPointer(goog::Message* message) const {
      return GetPointer<int32_t>(message, field_number_offset_);
    }

    void ClearOneof(goog::Message* m, const FieldOffset* ofs,
                    int field_number) const {
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
      if (GetArena(*m) != NULL) {
        return;
      }
#endif
      switch (types_.at(field_number)) {
        case ONEOF_TYPE_NONE:
          break;
        case ONEOF_TYPE_STRING:
          delete *ofs->GetFieldPointer<std::string*>(m);
          break;
        case ONEOF_TYPE_MESSAGE:
          delete *ofs->GetFieldPointer<goog::Message*>(m);
          break;
#ifdef UPB_GOOGLE3
        case ONEOF_TYPE_GLOBALSTRING:
          delete *ofs->GetFieldPointer<string*>(m);
          break;
        case ONEOF_TYPE_CORD:
          delete *ofs->GetFieldPointer<Cord*>(m);
          break;
        case ONEOF_TYPE_STRINGPIECE:
          delete *ofs->GetFieldPointer<
              goog::internal::StringPieceField*>(m);
          break;
        case ONEOF_TYPE_LAZYFIELD:
          delete *ofs->GetFieldPointer<goog::internal::LazyField*>(m);
          break;
#endif
      }
    }

    // Returns whether this is different than the previous value of the
    // field_number; this implies that the current value was freed (if
    // necessary) and the caller should allocate a new instance.
    bool SetOneofHas(goog::Message* m, const FieldOffset* ofs) const {
      int32_t *field_number = GetFieldPointer(m);
      if (*field_number == field_number_) {
        return false;
      } else {
        ClearOneof(m, ofs, *field_number);
        *field_number = field_number_;
        return true;
      }
    }

   private:
    enum OneofType {
      ONEOF_TYPE_NONE,
      ONEOF_TYPE_STRING,
      ONEOF_TYPE_MESSAGE
#ifdef UPB_GOOGLE3
      ,
      ONEOF_TYPE_GLOBALSTRING,
      ONEOF_TYPE_CORD,
      ONEOF_TYPE_STRINGPIECE,
      ONEOF_TYPE_LAZYFIELD
#endif
    };

    OneofType GetTypeForString(const goog::FieldDescriptor* f) {
      switch (f->options().ctype()) {
        case goog::FieldOptions::STRING:
#ifdef UPB_GOOGLE3
          return ONEOF_TYPE_GLOBALSTRING;
#else
          return ONEOF_TYPE_STRING;
#endif

#ifdef UPB_GOOGLE3
        case goog::FieldOptions::CORD:
          return ONEOF_TYPE_CORD;
        case goog::FieldOptions::STRING_PIECE:
          return ONEOF_TYPE_STRINGPIECE;
#endif
        default:
          assert(false);
          return ONEOF_TYPE_NONE;
      }
    }

    // Offset of the uint32 that specifies which field is set.
    size_t field_number_offset_;

    // Field number for this field.
    int32_t field_number_;

    // The types of the oneof fields, indexed by field_number_.
    std::map<int32_t, OneofType> types_;
  };

  class OneofFieldHandlerData : public FieldOffset {
   public:
    OneofFieldHandlerData(const goog::FieldDescriptor* f,
                          const goog::internal::GeneratedMessageReflection* r)
        : FieldOffset(f, r),
          oneof_data_(f, r) {}

    bool SetOneofHas(goog::Message* message) const {
      return oneof_data_.SetOneofHas(message, this);
    }

   public:
    OneofFieldData oneof_data_;
  };
#endif  // GOOGLE_PROTOBUF_HAS_ONEOF

  class ExtensionFieldData {
   public:
    ExtensionFieldData(
        const goog::FieldDescriptor* proto2_f,
        const goog::internal::GeneratedMessageReflection* r)
        : offset_(r->extensions_offset_),
          field_descriptor_(proto2_f) {
    }

    int number() const { return field_descriptor_->number(); }
    goog::internal::FieldType type() const { return field_descriptor_->type(); }
    const goog::FieldDescriptor* field_descriptor() const {
      return field_descriptor_;
    }

    goog::internal::ExtensionSet* GetExtensionSet(goog::Message* m) const {
      return GetPointer<goog::internal::ExtensionSet>(m, offset_);
    }

   private:
    const size_t offset_;
    // We know it will outlive because we require that the input message used to
    // build these handlers outlives us, and the descriptor will outlive the
    // message.
    const goog::FieldDescriptor* field_descriptor_;
  };

  // StartSequence /////////////////////////////////////////////////////////////

  template <class T>
  static void SetStartRepeatedField(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    CHKRET(h->SetStartSequenceHandler(
        f, UpbBindT(&PushOffset<goog::RepeatedField<T> >,
                    new FieldOffset(proto2_f, r))));
  }

  template <class T>
  static void SetStartRepeatedPtrField(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    CHKRET(h->SetStartSequenceHandler(
        f, UpbBindT(&PushOffset<goog::RepeatedPtrField<T> >,
                    new FieldOffset(proto2_f, r))));
  }

  static void SetStartRepeatedSubmessageField(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    CHKRET(h->SetStartSequenceHandler(
        f, UpbBind(&PushOffset<goog::internal::RepeatedPtrFieldBase>,
                   new FieldOffset(proto2_f, r))));
  }

  template <class T>
  static T* PushOffset(goog::Message* message, const FieldOffset* offset) {
    return offset->GetFieldPointer<T>(message);
  }

  // Primitive Value (numeric, bool) ///////////////////////////////////////////

  template <typename T> static void SetPrimitiveHandlers(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    if (proto2_f->is_extension()) {
      scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
      if (f->IsSequence()) {
        CHKRET(h->SetValueHandler<T>(
            f, UpbBindT(AppendPrimitiveExtension<T>, data.release())));
      } else {
        CHKRET(h->SetValueHandler<T>(
            f, UpbBindT(SetPrimitiveExtension<T>, data.release())));
      }
    }
#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
      else if (proto2_f->containing_oneof()) {
      assert(!proto2_f->is_repeated());
      CHKRET(h->SetValueHandler<T>(
          f, UpbBindT(SetOneofPrimitive<T>,
                      new OneofFieldHandlerData(proto2_f, r))));
    }
#endif
      else {
      if (f->IsSequence()) {
        SetStartRepeatedField<T>(proto2_f, r, f, h);
        CHKRET(h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>)));
      } else {
        CHKRET(upb::Shim::Set(h, f, GetOffset(proto2_f, r),
                              GetHasbit(proto2_f, r)));
      }
    }
  }

  template <typename T>
  static void AppendPrimitive(goog::RepeatedField<T>* r, T val) { r->Add(val); }

  template <typename T>
  static void AppendPrimitiveExtension(goog::Message* m,
                                       const ExtensionFieldData* data, T val) {
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    // TODO(haberman): give an accurate value for "packed"
    goog::internal::RepeatedPrimitiveTypeTraits<T>::Add(
        data->number(), data->type(), true, val, set);
  }

  template <typename T>
  static void SetPrimitiveExtension(goog::Message* m,
                                    const ExtensionFieldData* data, T val) {
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    goog::internal::PrimitiveTypeTraits<T>::Set(data->number(), data->type(),
                                                val, set);
  }

#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
  template <typename T>
  static void SetOneofPrimitive(goog::Message* m,
                                const OneofFieldHandlerData* data, T val) {
    data->SetOneofHas(m);
    const FieldOffset* ofs = data;
    T* ptr = ofs->GetFieldPointer<T>(m);
    *ptr = val;
  }
#endif

  // Enum //////////////////////////////////////////////////////////////////////

  class EnumHandlerData : public FieldOffset {
   public:
    EnumHandlerData(const goog::FieldDescriptor* proto2_f,
                    const goog::internal::GeneratedMessageReflection* r,
                    const upb::FieldDef* f)
        : FieldOffset(proto2_f, r),
          field_number_(f->number()),
          enum_(upb_downcast_enumdef(f->subdef())) {}

    bool IsValidValue(int32_t val) const {
      return enum_->FindValueByNumber(val) != NULL;
    }

    int32_t field_number() const { return field_number_; }

   private:
    int32_t field_number_;
    const upb::EnumDef* enum_;
  };

  static void SetEnumHandlers(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    assert(!proto2_f->is_extension());
    scoped_ptr<EnumHandlerData> data(new EnumHandlerData(proto2_f, r, f));
    if (f->IsSequence()) {
      CHKRET(h->SetInt32Handler(f, UpbBind(AppendEnum, data.release())));
    } else {
      CHKRET(h->SetInt32Handler(f, UpbBind(SetEnum, data.release())));
    }
  }

  static void SetEnum(goog::Message* m, const EnumHandlerData* data,
                      int32_t val) {
    if (data->IsValidValue(val)) {
      int32_t* message_val = data->GetFieldPointer<int32_t>(m);
      *message_val = val;
      data->SetHasbit(m);
    } else {
      data->GetUnknownFieldSet(m)->AddVarint(data->field_number(), val);
    }
  }

  static void AppendEnum(goog::Message* m, const EnumHandlerData* data,
                         int32_t val) {
    // Closure is the enclosing message.  We can't use the RepeatedField<> as
    // the closure because we need to go back to the message for unrecognized
    // enum values, which go into the unknown field set.
    if (data->IsValidValue(val)) {
      goog::RepeatedField<int32_t>* r =
          data->GetFieldPointer<goog::RepeatedField<int32_t> >(m);
      r->Add(val);
    } else {
      data->GetUnknownFieldSet(m)->AddVarint(data->field_number(), val);
    }
  }

  // EnumExtension /////////////////////////////////////////////////////////////

  static void SetEnumExtensionHandlers(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    assert(proto2_f->is_extension());
    scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
    if (f->IsSequence()) {
      CHKRET(
          h->SetInt32Handler(f, UpbBind(AppendEnumExtension, data.release())));
    } else {
      CHKRET(h->SetInt32Handler(f, UpbBind(SetEnumExtension, data.release())));
    }
  }

  static void SetEnumExtension(goog::Message* m, const ExtensionFieldData* data,
                               int32_t val) {
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    set->SetEnum(data->number(), data->type(), val, NULL);
  }

  static void AppendEnumExtension(goog::Message* m,
                                  const ExtensionFieldData* data, int32_t val) {
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    // TODO(haberman): give an accurate value for "packed"
    set->AddEnum(data->number(), data->type(), true, val, NULL);
  }

  // String ////////////////////////////////////////////////////////////////////

  // For scalar (non-repeated) string fields.
  template <class T> class StringHandlerData : public FieldOffset {
   public:
    StringHandlerData(const goog::FieldDescriptor* proto2_f,
                      const goog::internal::GeneratedMessageReflection* r)
        : FieldOffset(proto2_f, r),
          prototype_(*GetConstPointer<T*>(r->default_instance_,
                                          GetOffset(proto2_f, r))) {}

    const T* prototype() const { return prototype_; }

    T** GetStringPointer(goog::Message* message) const {
      return GetFieldPointer<T*>(message);
    }

   private:
    const T* prototype_;
  };

  template <typename T> static void SetStringHandlers(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f,
      upb::Handlers* h) {
    assert(!proto2_f->is_extension());
    CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>)));
#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
    if (proto2_f->containing_oneof()) {
      assert(!f->IsSequence());
      CHKRET(h->SetStartStringHandler(
          f, UpbBindT(&StartOneofString<T>,
                      new OneofFieldHandlerData(proto2_f, r))));
    } else
#endif
      if (f->IsSequence()) {
      SetStartRepeatedPtrField<T>(proto2_f, r, f, h);
      CHKRET(
          h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>)));
    } else {
      CHKRET(h->SetStartStringHandler(
          f, UpbBindT(StartString<T>, new StringHandlerData<T>(proto2_f, r))));
    }
  }

  // This needs to be templated because google3 string is not std::string.
  template <typename T>
  static T* StartString(goog::Message* m, const StringHandlerData<T>* data,
                        size_t size_hint) {
    UPB_UNUSED(size_hint);
    T** str = data->GetStringPointer(m);
    data->SetHasbit(m);
    // If it points to the default instance, we must create a new instance.
    if (*str == data->prototype()) {
      *str = new T();
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
      if (data->GetArena(*m)) {
        data->GetArena(*m)->Own(*str);
      }
#endif
    }
    (*str)->clear();
    // reserve() here appears to hurt performance rather than help.
    return *str;
  }

  template <typename T>
  static void OnStringBuf(T* str, const char* buf, size_t n) {
    str->append(buf, n);
  }

  template <typename T>
  static T* StartRepeatedString(goog::RepeatedPtrField<T>* r,
                                size_t size_hint) {
    UPB_UNUSED(size_hint);
    T* str = r->Add();
    str->clear();
    // reserve() here appears to hurt performance rather than help.
    return str;
  }

#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
  template <typename T>
  static T* StartOneofString(goog::Message* m,
                             const OneofFieldHandlerData* data,
                             size_t size_hint) {
    UPB_UNUSED(size_hint);
    const FieldOffset* ofs = data;
    T** str = ofs->GetFieldPointer<T*>(m);
    if (data->SetOneofHas(m)) {
      *str = new T();
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
      // Note that in the main proto2-arenas implementation, the parsing code
      // creates ArenaString instances for string field data, and the
      // implementation later dynamically converts to ::string if a mutable
      // version is requested. To keep complexity down in this binding, we
      // create an ordinary string and allow the arena to own its destruction.
      if (data->GetArena(*m) != NULL) {
        data->GetArena(*m)->Own(*str);
      }
#endif
    } else {
      (*str)->clear();
    }
    return *str;
  }
#endif

  // StringExtension ///////////////////////////////////////////////////////////

  template <typename T>
  static void SetStringExtensionHandlers(
      const goog::FieldDescriptor* proto2_f,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    assert(proto2_f->is_extension());
    CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(OnStringBuf<T>)));
    scoped_ptr<ExtensionFieldData> data(new ExtensionFieldData(proto2_f, r));
    if (f->IsSequence()) {
      CHKRET(h->SetStartStringHandler(
          f, UpbBindT(StartRepeatedStringExtension<T>, data.release())));
    } else {
      CHKRET(h->SetStartStringHandler(
          f, UpbBindT(StartStringExtension<T>, data.release())));
    }
  }

  // Templated because google3 is not std::string.
  template <class T>
  static T* StartStringExtension(goog::Message* m,
                                 const ExtensionFieldData* data,
                                 size_t size_hint) {
    UPB_UNUSED(size_hint);
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    return set->MutableString(data->number(), data->type(), NULL);
  }

  template <class T>
  static T* StartRepeatedStringExtension(goog::Message* m,
                                         const ExtensionFieldData* data,
                                         size_t size_hint) {
    UPB_UNUSED(size_hint);
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    return set->AddString(data->number(), data->type(), NULL);
  }

  // SubMessage ////////////////////////////////////////////////////////////////

  class SubMessageHandlerData : public FieldOffset {
   public:
    SubMessageHandlerData(const goog::FieldDescriptor* f,
                          const goog::internal::GeneratedMessageReflection* r,
                          const goog::Message* prototype)
        : FieldOffset(f, r), prototype_(prototype) {}

    const goog::Message* prototype() const { return prototype_; }

   private:
    const goog::Message* const prototype_;
  };

#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
  class OneofSubMessageHandlerData : public SubMessageHandlerData {
   public:
    OneofSubMessageHandlerData(const goog::FieldDescriptor* f,
                          const goog::internal::GeneratedMessageReflection* r,
                          const goog::Message* prototype)
        : SubMessageHandlerData(f, r, prototype),
          oneof_data_(f, r) {}

    bool SetOneofHas(goog::Message* m) const {
      return oneof_data_.SetOneofHas(m, this);
    }

   private:
    OneofFieldData oneof_data_;
  };
#endif

  static void SetSubMessageHandlers(
      const goog::FieldDescriptor* proto2_f, const goog::Message& m,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f);
    scoped_ptr<SubMessageHandlerData> data(
        new SubMessageHandlerData(proto2_f, r, field_prototype));
#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
    if (proto2_f->containing_oneof()) {
      assert(!f->IsSequence());
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartOneofSubMessage, new OneofSubMessageHandlerData(
                                               proto2_f, r, field_prototype))));
    } else
#endif
      if (f->IsSequence()) {
      SetStartRepeatedSubmessageField(proto2_f, r, f, h);
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartRepeatedSubMessage, data.release())));
    } else {
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartSubMessage, data.release())));
    }
  }

  static goog::Message* StartSubMessage(goog::Message* m,
                                        const SubMessageHandlerData* data) {
    data->SetHasbit(m);
    goog::Message** subm = data->GetFieldPointer<goog::Message*>(m);
    if (*subm == NULL || *subm == data->prototype()) {
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
      *subm = data->prototype()->New(data->GetArena(*m));
#else
      *subm = data->prototype()->New();
#endif
    }
    return *subm;
  }

  class RepeatedMessageTypeHandler {
   public:
    typedef goog::Message Type;
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    static goog::Arena* GetArena(Type* t) {
      return t->GetArena();
    }
    static void* GetMaybeArenaPointer(Type* t) {
      return t->GetMaybeArenaPointer();
    }
    static inline Type* NewFromPrototype(
        const Type* prototype, goog::Arena* arena = NULL) {
      return prototype->New(arena);
    }
    static void Delete(Type* t, goog::Arena* arena = NULL) {
      if (arena == NULL) {
        delete t;
      }
    }
#else  // ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    static inline Type* NewFromPrototype(const Type* prototype) {
      return prototype->New();
    }
    // AddAllocated() calls this, but only if other objects are sitting
    // around waiting for reuse, which we will not do.
    static void Delete(Type* t) {
      UPB_UNUSED(t);
      assert(false);
    }
#endif  // ifdef GOOGLE_PROTOBUF_HAS_ARENAS

    static void Merge(const Type& from, Type* to) {
      to->MergeFrom(from);
    }
  };

  // Closure is a RepeatedPtrField<SubMessageType>*, but we access it through
  // its base class RepeatedPtrFieldBase*.
  static goog::Message* StartRepeatedSubMessage(
      goog::internal::RepeatedPtrFieldBase* r,
      const SubMessageHandlerData* data) {
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    return r->Add<RepeatedMessageTypeHandler>(
        const_cast<goog::Message*>(data->prototype()));
#else
    // This code path is required not because of arena-related API changes but
    // because the variant of Add<>() that takes a prototype object was added
    // only recently. Without the prototype, there's no way for Add<>() to
    // create a new submessage with out typehandler implementation because we
    // don't have New() (because we don't template-specialize our typehandler
    // class on concrete message types). So we have to implement the runtime
    // polymorphism externally (in this function) and then use AddAllocated to
    // insert the pointer.
    goog::Message* submsg = r->AddFromCleared<RepeatedMessageTypeHandler>();
    if (!submsg) {
      submsg = data->prototype()->New();
      r->AddAllocated<RepeatedMessageTypeHandler>(submsg);
    }
    return submsg;
#endif
  }

#ifdef GOOGLE_PROTOBUF_HAS_ONEOF
  static goog::Message* StartOneofSubMessage(
      goog::Message* m, const OneofSubMessageHandlerData* data) {
    const FieldOffset* ofs = data;
    goog::Message** subm = ofs->GetFieldPointer<goog::Message*>(m);
    if (data->SetOneofHas(m)) {
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
      *subm = data->prototype()->New(data->GetArena(*m));
#else
      *subm = data->prototype()->New();
#endif
    }
    return *subm;
  }
#endif

  // SubMessageExtension ///////////////////////////////////////////////////////

  class SubMessageExtensionHandlerData : public ExtensionFieldData {
   public:
    SubMessageExtensionHandlerData(
        const goog::FieldDescriptor* proto2_f,
        const goog::internal::GeneratedMessageReflection* r,
        const goog::Message* prototype)
        : ExtensionFieldData(proto2_f, r),
          prototype_(prototype) {
    }

    const goog::Message* prototype() const { return prototype_; }

   private:
    const goog::Message* const prototype_;
  };

  static void SetSubMessageExtensionHandlers(
      const goog::FieldDescriptor* proto2_f,
      const goog::Message& m,
      const goog::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f,
      upb::Handlers* h) {
    const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f);
    scoped_ptr<SubMessageExtensionHandlerData> data(
        new SubMessageExtensionHandlerData(proto2_f, r, field_prototype));
    if (f->IsSequence()) {
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartRepeatedSubMessageExtension, data.release())));
    } else {
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartSubMessageExtension, data.release())));
    }
  }

  static goog::Message* StartRepeatedSubMessageExtension(
      goog::Message* m, const SubMessageExtensionHandlerData* data) {
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    // Because we found this message via a descriptor, we know it has a
    // descriptor and is therefore a Message and not a MessageLite.
    // Alternatively we could just use goog::MessageLite everywhere to avoid
    // this, but since they are in fact goog::Messages, it seems most clear
    // to refer to them as such.
    return CheckDownCast<goog::Message*>(set->AddMessage(
        data->number(), data->type(), *data->prototype(), NULL));
  }

  static goog::Message* StartSubMessageExtension(
      goog::Message* m, const SubMessageExtensionHandlerData* data) {
    goog::internal::ExtensionSet* set = data->GetExtensionSet(m);
    // See comment above re: this down cast.
    return CheckDownCast<goog::Message*>(set->MutableMessage(
        data->number(), data->type(), *data->prototype(), NULL));
  }

  // TODO(haberman): handle Unknown Fields.

#ifdef UPB_GOOGLE3
  // Handlers for types/features only included in internal proto2 release:
  // Cord, StringPiece, LazyField, and MessageSet.
  // TODO(haberman): MessageSet.

  // Cord //////////////////////////////////////////////////////////////////////

  static void AppendBufToCord(const char* buf, size_t n,
                              const upb::BufferHandle* handle, Cord* c) {
    const Cord* source_cord = handle->GetAttachedObject<Cord>();
    if (source_cord) {
      // This TODO is copied from CordReader::CopyToCord():
      // "We could speed this up by using CordReader internals."
      Cord piece(*source_cord);
      piece.RemovePrefix(handle->object_offset() + (buf - handle->buffer()));
      assert(piece.size() >= n);
      piece.RemoveSuffix(piece.size() - n);

      c->Append(piece);
    } else {
      c->Append(StringPiece(buf, n));
    }
  }

  static void SetCordHandlers(
      const proto2::FieldDescriptor* proto2_f,
      const proto2::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    assert(!proto2_f->is_extension());
    CHKRET(h->SetStringHandler(f, UpbMakeHandler(&OnCordBuf)));
    if (f->IsSequence()) {
      SetStartRepeatedField<Cord>(proto2_f, r, f, h);
      CHKRET(h->SetStartStringHandler(f, UpbMakeHandler(StartRepeatedCord)));
    } else {
      CHKRET(h->SetStartStringHandler(
          f, UpbBind(StartCord, new FieldOffset(proto2_f, r))));
    }
  }

  static Cord* StartCord(goog::Message* m, const FieldOffset* offset,
                         size_t size_hint) {
    UPB_UNUSED(size_hint);
    offset->SetHasbit(m);
    Cord* field = offset->GetFieldPointer<Cord>(m);
    field->Clear();
    return field;
  }

  static void OnCordBuf(Cord* c, const char* buf, size_t n,
                        const upb::BufferHandle* handle) {
    AppendBufToCord(buf, n, handle, c);
  }

  static Cord* StartRepeatedCord(proto2::RepeatedField<Cord>* r,
                                 size_t size_hint) {
    UPB_UNUSED(size_hint);
    return r->Add();
  }

  // StringPiece ///////////////////////////////////////////////////////////////

  static void SetStringPieceHandlers(
      const proto2::FieldDescriptor* proto2_f,
      const proto2::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    assert(!proto2_f->is_extension());
    CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnStringPieceBuf)));
    if (f->IsSequence()) {
      SetStartRepeatedPtrField<proto2::internal::StringPieceField>(proto2_f, r,
                                                                   f, h);
      CHKRET(h->SetStartStringHandler(
          f, UpbMakeHandler(StartRepeatedStringPiece)));
    } else {
      CHKRET(h->SetStartStringHandler(
          f, UpbBind(StartStringPiece, new FieldOffset(proto2_f, r))));
    }
  }

  static void OnStringPieceBuf(proto2::internal::StringPieceField* field,
                               const char* buf, size_t len) {
    // TODO(haberman): alias if possible and enabled on the input stream.
    // TODO(haberman): add a method to StringPieceField that lets us avoid
    // this copy/malloc/free.
    size_t new_len = field->size() + len;
    char* data = new char[new_len];
    memcpy(data, field->data(), field->size());
    memcpy(data + field->size(), buf, len);
    field->CopyFrom(StringPiece(data, new_len));
    delete[] data;
  }

  static proto2::internal::StringPieceField* StartStringPiece(
      goog::Message* m, const FieldOffset* offset, size_t size_hint) {
    UPB_UNUSED(size_hint);
    offset->SetHasbit(m);
    proto2::internal::StringPieceField* field =
        offset->GetFieldPointer<proto2::internal::StringPieceField>(m);
    field->Clear();
    return field;
  }

  static proto2::internal::StringPieceField* StartRepeatedStringPiece(
      proto2::RepeatedPtrField<proto2::internal::StringPieceField>* r,
      size_t size_hint) {
    UPB_UNUSED(size_hint);
    proto2::internal::StringPieceField* field = r->Add();
    field->Clear();
    return field;
  }

  // LazyField /////////////////////////////////////////////////////////////////

  // For lazy fields we set both lazy and eager handlers.  The user can
  // configure the data source to call either, though lazy handlers may only be
  // used when the source data is binary protobuf.
  static void SetLazyFieldHandlers(
      const proto2::FieldDescriptor* proto2_f,
      const proto2::Message& m,
      const proto2::internal::GeneratedMessageReflection* r,
      const upb::FieldDef* f, upb::Handlers* h) {
    assert(!proto2_f->is_repeated());
    const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f);
    CHKRET(h->SetStringHandler(f, UpbMakeHandler(OnLazyFieldBuf)));
    if (proto2_f->is_extension()) {
      CHKRET(h->SetStartStringHandler(
          f, UpbBind(StartLazyExtension, new ExtensionFieldData(proto2_f, r))));
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartSubMessageExtension,
                     new SubMessageExtensionHandlerData(proto2_f, r,
                                                        field_prototype))));
    } else {
      CHKRET(h->SetStartStringHandler(
          f, UpbBind(StartLazyField, new FieldOffset(proto2_f, r))));
      CHKRET(h->SetStartSubMessageHandler(
          f, UpbBind(StartLazyFieldEager,
                     new SubMessageHandlerData(proto2_f, r, field_prototype))));
    }
  }

  static proto2::internal::LazyField* StartLazyField(proto2::Message* m,
                                                     const FieldOffset* offset,
                                                     size_t size_hint) {
    UPB_UNUSED(size_hint);
    offset->SetHasbit(m);
    proto2::internal::LazyField* field =
        offset->GetFieldPointer<proto2::internal::LazyField>(m);
    field->Clear();
    return field;
  }

  // For when the field has a lazy representation but we parse it eagerly anyway
  // (either because we want to or because we're parsing from a format other
  // than binary protobuf).
  static proto2::Message* StartLazyFieldEager(
      proto2::Message* m, const SubMessageHandlerData* data) {
    data->SetHasbit(m);
    proto2::internal::LazyField* field =
        data->GetFieldPointer<proto2::internal::LazyField>(m);
    return field->MutableByPrototype(*data->prototype());
  }

  class LazyMessageExtensionImpl
      : public proto2::internal::ExtensionSet::LazyMessageExtension {
   public:
    LazyMessageExtensionImpl() {}
    virtual ~LazyMessageExtensionImpl() {}

#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    virtual LazyMessageExtension* New() const {
      return New(NULL);
    }

    virtual LazyMessageExtension* New(proto2::Arena* arena) const {
      LazyMessageExtensionImpl* message =
          ::proto2::Arena::Create<LazyMessageExtensionImpl>(arena);
      return message;
    }
#else  // ifdef GOOGLE_PROTOBUF_HAS_ARENAS
    virtual LazyMessageExtension* New() const {
      return new LazyMessageExtensionImpl();
    }
#endif  // ifdef GOOGLE_PROTOBUF_HAS_ARENAS

    virtual const proto2::MessageLite& GetMessage(
        const proto2::MessageLite& prototype) const {
      return lazy_field_.GetByPrototype(
          static_cast<const proto2::Message&>(prototype));
    }

    virtual proto2::MessageLite* MutableMessage(
        const proto2::MessageLite& prototype) {
      return lazy_field_.MutableByPrototype(
          static_cast<const proto2::Message&>(prototype));
    }

    virtual void SetAllocatedMessage(proto2::MessageLite* message) {
      return lazy_field_.SetAllocated(static_cast<proto2::Message*>(message));
    }

    virtual void UnsafeArenaSetAllocatedMessage(proto2::MessageLite* message) {
      return lazy_field_.UnsafeArenaSetAllocated(
          static_cast<proto2::Message*>(message));
    }

    virtual proto2::MessageLite* ReleaseMessage(
        const proto2::MessageLite& prototype) {
      return lazy_field_.ReleaseByPrototype(
          static_cast<const proto2::Message&>(prototype));
    }

    virtual proto2::MessageLite* UnsafeArenaReleaseMessage(
        const proto2::MessageLite& prototype) {
      return lazy_field_.UnsafeArenaReleaseByPrototype(
          static_cast<const proto2::Message&>(prototype));
    }

    virtual bool IsInitialized() const { return true; }

    virtual int ByteSize() const { return lazy_field_.MessageByteSize(); }

    int SpaceUsed() const {
      return sizeof(*this) + lazy_field_.SpaceUsedExcludingSelf();
    }

    virtual void MergeFrom(const LazyMessageExtension& other) {
      MergeFrom(*static_cast<const LazyMessageExtensionImpl*>(&other));
    }

    virtual void MergeFrom(const LazyMessageExtensionImpl& other) {
      lazy_field_.MergeFrom(other.lazy_field_);
    }

    virtual void Clear() { lazy_field_.Clear(); }

    virtual bool ReadMessage(const proto2::MessageLite& prototype,
                             proto2::io::CodedInputStream* input) {
      return lazy_field_.Read(input);
    }

    virtual void WriteMessage(int number,
                              proto2::io::CodedOutputStream* output) const {
      lazy_field_.Write(number, output);
    }

    virtual uint8* WriteMessageToArray(int number, uint8* target) const {
      return lazy_field_.WriteToArray(number, target);
    }

    proto2::internal::LazyField& lazy_field() { return lazy_field_; }

   private:
    proto2::internal::LazyField lazy_field_;
    DISALLOW_COPY_AND_ASSIGN(LazyMessageExtensionImpl);
  };

  static proto2::internal::LazyField* StartLazyExtension(
      proto2::Message* m, const ExtensionFieldData* data, size_t size_hint) {
    proto2::internal::ExtensionSet* set = data->GetExtensionSet(m);

    // We have to break encapsulation here since no public accessors expose the
    // LazyField.
    //
    // TODO(haberman): add a function to ExtensionSet that allows us to set the
    // lazy field directly.
    proto2::internal::ExtensionSet::Extension* item;
    LazyMessageExtensionImpl* lazy_extension;
    if (set->MaybeNewExtension(data->number(), data->field_descriptor(),
                               &item)) {
#ifdef GOOGLE_PROTOBUF_HAS_ARENAS
      lazy_extension =
          ::proto2::Arena::Create<LazyMessageExtensionImpl>(
              m->GetArena());
#else
      lazy_extension = new LazyMessageExtensionImpl();
#endif
      item->type = UPB_DESCRIPTOR_TYPE_MESSAGE;
      item->is_repeated = false;
      item->is_lazy = true;
      item->lazymessage_value = lazy_extension;
    } else {
      lazy_extension =
          CheckDownCast<LazyMessageExtensionImpl*>(item->lazymessage_value);
    }

    item->is_cleared = false;

    return &lazy_extension->lazy_field();
  }

  static void OnLazyFieldBuf(proto2::internal::LazyField* field,
                             const char* buf, size_t len,
                             const upb::BufferHandle* handle) {
    Cord encoded(field->GetEncoded());
    AppendBufToCord(buf, len, handle, &encoded);
    field->SetEncoded(encoded);
  }

#endif  // UPB_GOOGLE3
};

namespace upb {
namespace googlepb {

bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f,
                         const goog::Message& prototype,
                         const upb::FieldDef* upb_f, upb::Handlers* h) {
  return me::GMR_Handlers::TrySet(proto2_f, prototype, upb_f, h);
}

const goog::Message* GetProto2FieldPrototype(const goog::Message& m,
                                             const goog::FieldDescriptor* f) {
  if (f->cpp_type() != goog::FieldDescriptor::CPPTYPE_MESSAGE) {
    return NULL;
  }
  return me::GMR_Handlers::GetFieldPrototype(m, f);
}

}  // namespace googlepb
}  // namespace upb
